Repository: Andy53/ERC.Xdbg Branch: master Commit: 81a8ed009325 Files: 136 Total size: 3.8 MB Directory structure: gitextract_3ejl9pf4/ ├── .gitattributes ├── .gitignore ├── DllExport.bat ├── ERC/ │ ├── .gitignore │ ├── Documentation/ │ │ ├── .gitignore │ │ ├── api/ │ │ │ ├── .gitignore │ │ │ └── index.md │ │ ├── articles/ │ │ │ ├── LICENSE.md │ │ │ ├── intro.md │ │ │ └── toc.yml │ │ ├── docfx.json │ │ ├── index.md │ │ └── toc.yml │ ├── ERC/ │ │ ├── .gitignore │ │ ├── Convert.cs │ │ ├── Display_Output.cs │ │ ├── ERC.Net.csproj │ │ ├── ERC.Net.xml │ │ ├── ERCException.cs │ │ ├── ERC_Core.cs │ │ ├── FodyWeavers.xml │ │ ├── FodyWeavers.xsd │ │ ├── Heap_Info.cs │ │ ├── Module_Info.cs │ │ ├── Opcode_Assembler.cs │ │ ├── Opcode_Disassembler.cs │ │ ├── Pattern_Tools.cs │ │ ├── Payloads.cs │ │ ├── Process_Info.cs │ │ ├── PtrRemover.cs │ │ ├── RopChainGenerator32.cs │ │ ├── RopChainGenerator64.cs │ │ ├── Thread_Info.cs │ │ └── Win32Errors.cs │ ├── LICENSE │ ├── README.md │ └── docs/ │ ├── api/ │ │ ├── ERC.DisplayOutput.html │ │ ├── ERC.ERCException.html │ │ ├── ERC.ErcCore.html │ │ ├── ERC.ErcResult-1.html │ │ ├── ERC.MachineType.html │ │ ├── ERC.ModuleInfo.html │ │ ├── ERC.ProcessInfo.html │ │ ├── ERC.Structures.AllocationProtect.html │ │ ├── ERC.Structures.CONTEXT32.html │ │ ├── ERC.Structures.CONTEXT64.html │ │ ├── ERC.Structures.CONTEXT_FLAGS.html │ │ ├── ERC.Structures.ClientID.html │ │ ├── ERC.Structures.FLOATING_SAVE_AREA.html │ │ ├── ERC.Structures.IMAGE_DATA_DIRECTORY.html │ │ ├── ERC.Structures.IMAGE_DOS_HEADER.html │ │ ├── ERC.Structures.IMAGE_FILE_HEADER.html │ │ ├── ERC.Structures.IMAGE_LOAD_CONFIG_CODE_INTEGRITY.html │ │ ├── ERC.Structures.IMAGE_LOAD_CONFIG_DIRECTORY32.html │ │ ├── ERC.Structures.IMAGE_LOAD_CONFIG_DIRECTORY64.html │ │ ├── ERC.Structures.IMAGE_NT_HEADERS32.html │ │ ├── ERC.Structures.IMAGE_NT_HEADERS64.html │ │ ├── ERC.Structures.IMAGE_OPTIONAL_HEADER32.html │ │ ├── ERC.Structures.IMAGE_OPTIONAL_HEADER64.html │ │ ├── ERC.Structures.LIST_ENTRY.html │ │ ├── ERC.Structures.LOADED_IMAGE.html │ │ ├── ERC.Structures.LoadLibraryFlags.html │ │ ├── ERC.Structures.M128A.html │ │ ├── ERC.Structures.MEMORY_BASIC_INFORMATION32.html │ │ ├── ERC.Structures.MEMORY_BASIC_INFORMATION64.html │ │ ├── ERC.Structures.MagicType.html │ │ ├── ERC.Structures.ProcessAccessFlags.html │ │ ├── ERC.Structures.RegisterInfo.html │ │ ├── ERC.Structures.StateEnum.html │ │ ├── ERC.Structures.SubSystemType.html │ │ ├── ERC.Structures.TEB.html │ │ ├── ERC.Structures.ThreadAccess.html │ │ ├── ERC.Structures.ThreadBasicInformation.html │ │ ├── ERC.Structures.TypeEnum.html │ │ ├── ERC.Structures.XSAVE_FORMAT64.html │ │ ├── ERC.Structures.html │ │ ├── ERC.ThreadInfo.html │ │ ├── ERC.Utilities.Convert.html │ │ ├── ERC.Utilities.OpcodeAssembler.html │ │ ├── ERC.Utilities.OpcodeDisassembler.html │ │ ├── ERC.Utilities.PatternTools.html │ │ ├── ERC.Utilities.Payloads.html │ │ ├── ERC.Utilities.PtrRemover.html │ │ ├── ERC.Utilities.RopChainGenerator32.X86Lists.html │ │ ├── ERC.Utilities.RopChainGenerator32.html │ │ ├── ERC.Utilities.RopChainGenerator64.X64Lists.html │ │ ├── ERC.Utilities.RopChainGenerator64.html │ │ ├── ERC.Utilities.html │ │ ├── ERC.html │ │ ├── index.html │ │ └── toc.html │ ├── articles/ │ │ ├── LICENSE.html │ │ ├── intro.html │ │ └── toc.html │ ├── index.html │ ├── manifest.json │ ├── search-stopwords.json │ ├── styles/ │ │ ├── docfx.css │ │ ├── docfx.js │ │ ├── docfx.vendor.css │ │ ├── docfx.vendor.js │ │ ├── lunr.js │ │ ├── main.css │ │ ├── main.js │ │ └── search-worker.js │ ├── toc.html │ └── xrefmap.yml ├── ERC.net/ │ └── ERC/ │ └── ERC.Net.xml ├── ErcXdbg/ │ ├── AssemblyInfo.cs │ ├── ErcMain.cs │ ├── ErcXdbg.cs │ ├── ErcXdbgPlugin.csproj │ ├── FodyWeavers.xml │ ├── FodyWeavers.xsd │ ├── Globals.cs │ ├── RegisteredCommands.cs │ ├── app.config │ └── packages.config ├── ErcXdbgPlugin.sln ├── LICENSE ├── Managed.x64dbg/ │ ├── FodyWeavers.xml │ ├── FodyWeavers.xsd │ ├── Managed.x64dbg.csproj │ ├── Properties/ │ │ └── AssemblyInfo.cs │ ├── SDK/ │ │ ├── Bridge.cs │ │ ├── Extensions.cs │ │ ├── PLog.cs │ │ ├── Plugins.cs │ │ ├── TitanEngine.cs │ │ └── WAPI.cs │ ├── Script/ │ │ └── Module.cs │ ├── app.config │ └── packages.config ├── README.md └── packages/ ├── .gitignore └── repositories.config ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitattributes ================================================ * linguist-language=csharp ================================================ FILE: .gitignore ================================================ ## Ignore Visual Studio temporary files, build results, and ## files generated by popular Visual Studio add-ons. ## ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore # User-specific files *.suo *.user *.userosscache *.sln.docstates # User-specific files (MonoDevelop/Xamarin Studio) *.userprefs # Build results [Dd]ebug/ [Dd]ebugPublic/ [Rr]elease/ [Rr]eleases/ x64/ x86/ bld/ [Bb]in/ [Oo]bj/ [Ll]og/ # Visual Studio 2015/2017 cache/options directory .vs/ # Uncomment if you have tasks that create the project's static files in wwwroot #wwwroot/ # Visual Studio 2017 auto generated files Generated\ Files/ # MSTest test Results [Tt]est[Rr]esult*/ [Bb]uild[Ll]og.* # NUNIT *.VisualState.xml TestResult.xml # Build Results of an ATL Project [Dd]ebugPS/ [Rr]eleasePS/ dlldata.c # Benchmark Results BenchmarkDotNet.Artifacts/ # .NET Core project.lock.json project.fragment.lock.json artifacts/ **/Properties/launchSettings.json # StyleCop StyleCopReport.xml # Files built by Visual Studio *_i.c *_p.c *_i.h *.ilk *.meta *.obj *.iobj *.pch *.pdb *.ipdb *.pgc *.pgd *.rsp *.sbr *.tlb *.tli *.tlh *.tmp *.tmp_proj *.log *.vspscc *.vssscc .builds *.pidb *.svclog *.scc # Chutzpah Test files _Chutzpah* # Visual C++ cache files ipch/ *.aps *.ncb *.opendb *.opensdf *.sdf *.cachefile *.VC.db *.VC.VC.opendb # Visual Studio profiler *.psess *.vsp *.vspx *.sap # Visual Studio Trace Files *.e2e # TFS 2012 Local Workspace $tf/ # Guidance Automation Toolkit *.gpState # ReSharper is a .NET coding add-in _ReSharper*/ *.[Rr]e[Ss]harper *.DotSettings.user # JustCode is a .NET coding add-in .JustCode # TeamCity is a build add-in _TeamCity* # DotCover is a Code Coverage Tool *.dotCover # AxoCover is a Code Coverage Tool .axoCover/* !.axoCover/settings.json # Visual Studio code coverage results *.coverage *.coveragexml # NCrunch _NCrunch_* .*crunch*.local.xml nCrunchTemp_* # MightyMoose *.mm.* AutoTest.Net/ # Web workbench (sass) .sass-cache/ # Installshield output folder [Ee]xpress/ # DocProject is a documentation generator add-in DocProject/buildhelp/ DocProject/Help/*.HxT DocProject/Help/*.HxC DocProject/Help/*.hhc DocProject/Help/*.hhk DocProject/Help/*.hhp DocProject/Help/Html2 DocProject/Help/html # Click-Once directory publish/ # Publish Web Output *.[Pp]ublish.xml *.azurePubxml # Note: Comment the next line if you want to checkin your web deploy settings, # but database connection strings (with potential passwords) will be unencrypted *.pubxml *.publishproj # Microsoft Azure Web App publish settings. Comment the next line if you want to # checkin your Azure Web App publish settings, but sensitive information contained # in these scripts will be unencrypted PublishScripts/ # NuGet Packages *.nupkg # The packages folder can be ignored because of Package Restore **/[Pp]ackages/* # except build/, which is used as an MSBuild target. !**/[Pp]ackages/build/ # Uncomment if necessary however generally it will be regenerated when needed #!**/[Pp]ackages/repositories.config # NuGet v3's project.json files produces more ignorable files *.nuget.props *.nuget.targets # Microsoft Azure Build Output csx/ *.build.csdef # Microsoft Azure Emulator ecf/ rcf/ # Windows Store app package directories and files AppPackages/ BundleArtifacts/ Package.StoreAssociation.xml _pkginfo.txt *.appx # Visual Studio cache files # files ending in .cache can be ignored *.[Cc]ache # but keep track of directories ending in .cache !*.[Cc]ache/ # Others ClientBin/ ~$* *~ *.dbmdl *.dbproj.schemaview *.jfm *.pfx *.publishsettings orleans.codegen.cs # Including strong name files can present a security risk # (https://github.com/github/gitignore/pull/2483#issue-259490424) #*.snk # Since there are multiple workflows, uncomment next line to ignore bower_components # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) #bower_components/ # RIA/Silverlight projects Generated_Code/ # Backup & report files from converting an old project file # to a newer Visual Studio version. Backup files are not needed, # because we have git ;-) _UpgradeReport_Files/ Backup*/ UpgradeLog*.XML UpgradeLog*.htm ServiceFabricBackup/ *.rptproj.bak # SQL Server files *.mdf *.ldf *.ndf # Business Intelligence projects *.rdl.data *.bim.layout *.bim_*.settings *.rptproj.rsuser # Microsoft Fakes FakesAssemblies/ # GhostDoc plugin setting file *.GhostDoc.xml # Node.js Tools for Visual Studio .ntvs_analysis.dat node_modules/ # Visual Studio 6 build log *.plg # Visual Studio 6 workspace options file *.opt # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) *.vbw # Visual Studio LightSwitch build output **/*.HTMLClient/GeneratedArtifacts **/*.DesktopClient/GeneratedArtifacts **/*.DesktopClient/ModelManifest.xml **/*.Server/GeneratedArtifacts **/*.Server/ModelManifest.xml _Pvt_Extensions # Paket dependency manager .paket/paket.exe paket-files/ # FAKE - F# Make .fake/ # JetBrains Rider .idea/ *.sln.iml # CodeRush .cr/ # Python Tools for Visual Studio (PTVS) __pycache__/ *.pyc # Cake - Uncomment if you are using it # tools/** # !tools/packages.config # Tabs Studio *.tss # Telerik's JustMock configuration file *.jmconfig # BizTalk build output *.btp.cs *.btm.cs *.odx.cs *.xsd.cs # OpenCover UI analysis results OpenCover/ # Azure Stream Analytics local run output ASALocalRun/ # MSBuild Binary and Structured Log *.binlog # NVidia Nsight GPU debugger configuration file *.nvuser # MFractors (Xamarin productivity tool) working folder .mfractor/ ================================================ FILE: DllExport.bat ================================================ @echo off :: Copyright (c) 2016-2021 Denis Kuzmin [x-3F@outlook.com] github/3F :: https://github.com/3F/DllExport if "%~1"=="/?" goto bq set "aa=%~dpnx0" set ab=%* set ac=%* if defined ab ( if defined __p_call ( set ac=%ac:^^=^% ) else ( set ab=%ab:^=^^% ) ) set wMgrArgs=%ac% set ad=%ab:!=^!% setlocal enableDelayedExpansion set "ae=^" set "ad=!ad:%%=%%%%!" set "ad=!ad:&=%%ae%%&!" set "af=1.7.4" set "wAction=Configure" set "ag=DllExport" set "ah=tools/net.r_eg.DllExport.Wizard.targets" set "ai=packages" set "aj=https://www.nuget.org/api/v2/package/" set "ak=build_info.txt" set "al=!aa!" set "wRootPath=!cd!" set /a wDxpOpt=0 set "am=" set "an=" set "ao=" set "ap=" set "aq=" set "ar=" set "as=" set "at=" set "au=" set "av=" set /a aw=0 if not defined ab ( if defined wAction goto br goto bq ) call :bs bk !ad! bl goto bt :bq echo. @echo .NET DllExport v1.7.4.29858+c1cc52f @echo Copyright (c) 2009-2015 Robert Giesecke @echo Copyright (c) 2016-2021 Denis Kuzmin ^ github/3F echo. echo MIT License @echo https://github.com/3F/DllExport echo Based on hMSBuild, MvsSln, +GetNuTool: https://github.com/3F echo. @echo. @echo Usage: DllExport [args to DllExport] [args to GetNuTool] [args to hMSBuild] echo ------ echo. echo Arguments echo --------- echo -action {type} - Specified action for Wizard. Where {type}: echo * Configure - To configure DllExport for specific projects. echo * Update - To update pkg reference for already configured projects. echo * Restore - To restore configured DllExport. echo * Export - To export configured projects data. echo * Recover - To re-configure projects via predefined/exported data. echo * Unset - To unset all data from specified projects. echo * Upgrade - Aggregates an Update action with additions for upgrading. echo. echo -sln-dir {path} - Path to directory with .sln files to be processed. echo -sln-file {path} - Optional predefined .sln file to be processed. echo -metalib {path} - Relative path to meta library. echo -metacor {path} - Relative path to meta core library. echo -dxp-target {path} - Relative path to entrypoint wrapper of the main core. echo -dxp-version {num} - Specific version of DllExport. Where {num}: echo * Versions: 1.7.3 ... echo * Keywords: echo `actual` - Unspecified local/latest remote version; echo ( Only if you know what you are doing ) echo. echo -msb {path} - Full path to specific msbuild. echo -hMSBuild {args} - Access to hMSBuild tool (packed) https://github.com/3F/hMSBuild echo -packages {path} - A common directory for packages. echo -server {url} - Url for searching remote packages. echo -proxy {cfg} - To use proxy. The format: [usr[:pwd]@]host[:port] echo -pkg-link {uri} - Direct link to package from the source via specified URI. echo -force - Aggressive behavior, e.g. like removing pkg when updating. echo -no-mgr - Do not use %~nx0 for automatic restore the remote package. echo -mgr-up - Updates %~nx0 to version from '-dxp-version'. echo -wz-target {path} - Relative path to entrypoint wrapper of the main wizard. echo -pe-exp-list {module} - To list all available exports from PE32/PE32+ module. echo -eng - Try to use english language for all build messages. echo -GetNuTool {args} - Access to GetNuTool (integrated) https://github.com/3F/GetNuTool echo -debug - To show additional information. echo -version - Displays version for which (together with) it was compiled. echo -build-info - Displays actual build information from selected DllExport. echo -help - Displays this help. Aliases: -help -h echo. echo Flags echo ----- echo __p_call - To use the call-type logic when invoking %~nx0 echo. echo Samples echo ------- echo DllExport -action Configure -force -pkg-link http://host/v1.7.3.nupkg echo DllExport -action Restore -sln-file "Conari.sln" echo DllExport -proxy guest:1234@10.0.2.15:7428 -action Configure echo. echo DllExport -mgr-up -dxp-version 1.7.3 echo DllExport -action Upgrade -dxp-version 1.7.3 echo. echo DllExport -GetNuTool /p:ngpackages="Conari;regXwild" echo DllExport -pe-exp-list bin\Debug\regXwild.dll goto bu :bt set /a ax=0 :bv set ay=!bk[%ax%]! if [!ay!]==[-help] ( goto bq ) else if [!ay!]==[-h] ( goto bq ) else if [!ay!]==[-?] ( goto bq ) if [!ay!]==[-debug] ( set am=1 goto bw ) else if [!ay!]==[-action] ( set /a "ax+=1" & call :bx bk[!ax!] v set wAction=!v! for %%g in (Restore, Configure, Update, Export, Recover, Unset, Upgrade, Default) do ( if "!v!"=="%%g" goto bw ) echo Unknown -action !v! exit/B 1 ) else if [!ay!]==[-sln-dir] ( set /a "ax+=1" & call :bx bk[!ax!] v set wSlnDir=!v! goto bw ) else if [!ay!]==[-sln-file] ( set /a "ax+=1" & call :bx bk[!ax!] v set wSlnFile=!v! goto bw ) else if [!ay!]==[-metalib] ( set /a "ax+=1" & call :bx bk[!ax!] v set wMetaLib=!v! goto bw ) else if [!ay!]==[-metacor] ( set /a "ax+=1" & call :bx bk[!ax!] v set wMetaCor=!v! goto bw ) else if [!ay!]==[-dxp-target] ( set /a "ax+=1" & call :bx bk[!ax!] v set wDxpTarget=!v! goto bw ) else if [!ay!]==[-dxp-version] ( set /a "ax+=1" & call :bx bk[!ax!] v set af=!v! goto bw ) else if [!ay!]==[-msb] ( set /a "ax+=1" & call :bx bk[!ax!] v set ao=!v! goto bw ) else if [!ay!]==[-packages] ( set /a "ax+=1" & call :bx bk[!ax!] v set ai=!v! goto bw ) else if [!ay!]==[-server] ( set /a "ax+=1" & call :bx bk[!ax!] v set aj=!v! goto bw ) else if [!ay!]==[-proxy] ( set /a "ax+=1" & call :bx bk[!ax!] v set at=!v! set wProxy=!v! goto bw ) else if [!ay!]==[-pkg-link] ( set /a "ax+=1" & call :bx bk[!ax!] v set ap=!v! set af=!ay! goto bw ) else if [!ay!]==[-force] ( set ar=1 goto bw ) else if [!ay!]==[-no-mgr] ( set /a wDxpOpt^|=1 goto bw ) else if [!ay!]==[-mgr-up] ( set as=1 goto bw ) else if [!ay!]==[-wz-target] ( set /a "ax+=1" & call :bx bk[!ax!] v set ah=!v! goto bw ) else if [!ay!]==[-pe-exp-list] ( set /a "ax+=1" & call :bx bk[!ax!] v set aq=!v! goto bw ) else if [!ay!]==[-eng] ( chcp 437 >nul goto bw ) else if [!ay!]==[-GetNuTool] ( call :by -GetNuTool 10 set /a aw=!ERRORLEVEL! & goto bu ) else if [!ay!]==[-hMSBuild] ( set av=1 & goto br ) else if [!ay!]==[-version] ( @echo v1.7.4.29858+c1cc52f %__dxp_pv% goto bu ) else if [!ay!]==[-build-info] ( set an=1 goto bw ) else if [!ay!]==[-tests] ( set /a "ax+=1" & call :bx bk[!ax!] v set au=!v! goto bw ) else ( echo Incorrect key: !ay! set /a aw=1 goto bu ) :bw set /a "ax+=1" & if %ax% LSS !bl! goto bv :br call :bz "dxpName = " ag call :bz "dxpVersion = " af call :bz "-sln-dir = " wSlnDir call :bz "-sln-file = " wSlnFile call :bz "-metalib = " wMetaLib call :bz "-metacor = " wMetaCor call :bz "-dxp-target = " wDxpTarget call :bz "-wz-target = " ah call :bz "#opt " wDxpOpt if defined af ( if "!af!"=="actual" ( set "af=" ) ) set wPkgVer=!af! if z%wAction%==zUpgrade ( call :bz "Upgrade is on" set as=1 set ar=1 ) call :b0 ai set "ai=!ai!\\" set "az=!ag!" set "wPkgPath=!ai!!ag!" if defined af ( set "az=!az!/!af!" set "wPkgPath=!wPkgPath!.!af!" ) if defined ar ( if exist "!wPkgPath!" ( call :bz "Removing old version before continue. '-force' key rule. " wPkgPath rmdir /S/Q "!wPkgPath!" ) ) set a0="!wPkgPath!\\!ah!" call :bz "wPkgPath = " wPkgPath if not exist !a0! ( if exist "!wPkgPath!" ( call :bz "Trying to replace obsolete version ... " wPkgPath rmdir /S/Q "!wPkgPath!" ) call :bz "-pkg-link = " ap call :bz "-server = " aj if defined ap ( set aj=!ap! if "!aj::=!"=="!aj!" ( set aj=!cd!/!aj! ) if "!wPkgPath::=!"=="!wPkgPath!" ( set "a1=../" ) set "az=:!a1!!wPkgPath!|" ) if defined ao ( set a2=-msbuild "!ao!" ) set a3=!a2! /p:ngserver="!aj!" /p:ngpackages="!az!" /p:ngpath="!ai!" /p:proxycfg="!at! " call :bz "GetNuTool call: " a3 if defined am ( call :b1 !a3! ) else ( call :b1 !a3! >nul ) ) if defined av ( call :by -hMSBuild 9 set /a aw=!ERRORLEVEL! & goto bu ) if defined aq ( "!wPkgPath!\\tools\\PeViewer.exe" -list -pemodule "!aq!" set /a aw=%ERRORLEVEL% goto bu ) if defined an ( call :bz "buildInfo = " wPkgPath ak if not exist "!wPkgPath!\\!ak!" ( echo information about build is not available. set /a aw=2 goto bu ) type "!wPkgPath!\\!ak!" goto bu ) if not exist !a0! ( echo Something went wrong. Try to use another keys. set /a aw=2 goto bu ) call :bz "wRootPath = " wRootPath call :bz "wAction = " wAction call :bz "wMgrArgs = " wMgrArgs if defined ao ( call :bz "Use specific MSBuild tools: " ao set a4="!ao!" goto b2 ) call :b3 bm & set a4="!bm!" if "!ERRORLEVEL!"=="0" goto b2 echo MSBuild tools was not found. Try with `-msb` key. set /a aw=2 goto bu :b2 if not defined a4 ( echo Something went wrong. Use `-debug` key for details. set /a aw=2 goto bu ) if not defined au ( if not defined ao if defined wPkgPath ( set a4="!wPkgPath!\\hMSBuild" for /f "tokens=*" %%i in ('!a4! -version') do set a5=%%i call :b4 !a5! bn call :bz "hMSBuild -v" a5 bn if !bn! GEQ 230 ( call :bz "2.3+" set a4=!a4! -vsw-as "-requiresAny -requires Microsoft.NetCore.Component.SDK Microsoft.Net.Core.Component.SDK -products * -latest -prerelease" ) ) call :bz "Target: " a4 a0 call !a4! /nologo /v:m /m:4 !a0! ) :bu if defined au ( echo Running Tests ... "!au!" call :b3 bo "!bo!" /nologo /v:m /m:4 "!au!" exit/B 0 ) if defined as ( (copy /B/Y "!wPkgPath!\\DllExport.bat" "!al!" > nul) && ( echo Manager has been updated. & exit/B 0 ) || ( (echo -mgr-up failed:!aw! 1>&2) & exit/B 1 ) ) exit/B !aw! :b4 set a6=%~1 for /f "tokens=1,2 delims=." %%a in ("!a6!") do ( set _=%%b & set /a _*=10 & set /a %2=%%a!_! ) exit/B 0 :by set ay=%~1 set /a a7=%~2 call :bz "accessing to !ay! ..." for /L %%p IN (0,1,8181) DO ( if "!ad:~%%p,%a7%!"=="!ay!" ( set a8=!ad:~%%p! set a9=!a8:~%a7%! if defined av ( call "!wPkgPath!\\hMSBuild" !a9! ) else ( call :b1 !a9! ) exit/B !ERRORLEVEL! ) ) call :bz "!ay! is corrupted: " ad exit/B 1 :b3 call :bz "Searching from .NET Framework - .NET 4.0, ..." for %%v in (4.0, 3.5, 2.0) do ( call :b5 %%v Y & if defined Y ( set %1=!Y! exit/B 0 ) ) call :bz "msb -netfx: not found" set "%1=" exit/B 2 :b5 call :bz "check %1" for /F "usebackq tokens=2* skip=2" %%a in ( `reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSBuild\ToolsVersions\%1" /v MSBuildToolsPath 2^> nul` ) do if exist %%b ( set a_=%%~b call :bz ":msbfound " a_ call :b6 a_ bp set %2=!bp! exit/B 0 ) set "%2=" exit/B 0 :b6 set %2=!%~1!\MSBuild.exe exit/B 0 :bz if defined am ( set ba=%1 set ba=!ba:~0,-1! set ba=!ba:~1! echo.[%TIME% ] !ba! !%2! !%3! ) exit/B 0 :b0 call :b7 %1 call :b8 %1 exit/B 0 :b7 call :b9 %1 "-=1" exit/B 0 :b8 call :b9 %1 "+=1" exit/B 0 :b9 set bb=z!%1!z if "%~2"=="-=1" (set "bc=1") else (set "bc=") if defined bc ( set /a "i=-2" ) else ( set /a "i=1" ) :b_ if "!bb:~%i%,1!"==" " ( set /a "i%~2" goto b_ ) if defined bc set /a "i+=1" if defined bc ( set "%1=!bb:~1,%i%!" ) else ( set "%1=!bb:~%i%,-1!" ) exit/B 0 :bs set "bd=%~1" set /a ax=-1 :ca set /a ax+=1 set %bd%[!ax!]=%~2 shift & if not "%~3"=="" goto ca set /a ax-=1 set %1=!ax! exit/B 0 :bx set %2=!%1! exit/B 0 :b1 setlocal disableDelayedExpansion @echo off :: GetNuTool - Executable version :: Copyright (c) 2015-2018,2020 Denis Kuzmin [ x-3F@outlook.com ] :: https://github.com/3F/GetNuTool set be=gnt.core set bf="%temp%\%random%%random%%be%" if "%~1"=="-unpack" goto cb set bg=%* if defined __p_call if defined bg set bg=%bg:^^=^% set bh=%__p_msb% if defined bh goto cc if "%~1"=="-msbuild" goto cd for %%v in (4.0, 14.0, 12.0, 3.5, 2.0) do ( for /F "usebackq tokens=2* skip=2" %%a in ( `reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSBuild\ToolsVersions\%%v" /v MSBuildToolsPath 2^> nul` ) do if exist %%b ( set bh="%%~b\MSBuild.exe" goto cc ) ) echo MSBuild was not found. Try -msbuild "fullpath" args 1>&2 exit/B 2 :cd shift set bh=%1 shift set bi=%bg:!= #__b_ECL## % setlocal enableDelayedExpansion set bi=!bi:%%=%%%%! :ce for /F "tokens=1* delims==" %%a in ("!bi!") do ( if "%%~b"=="" ( call :cf !bi! exit/B %ERRORLEVEL% ) set bi=%%a #__b_EQ## %%b ) goto ce :cf shift & shift set "bg=" :cg set bg=!bg! %1 shift & if not "%~2"=="" goto cg set bg=!bg: #__b_EQ## ==! setlocal disableDelayedExpansion set bg=%bg: #__b_ECL## =!% :cc call :ch call %bh% %bf% /nologo /p:wpath="%cd%/" /v:m /m:4 %bg% set "bh=" set bj=%ERRORLEVEL% del /Q/F %bf% exit/B %bj% :cb set bf="%cd%\%be%" echo Generating minified version in %bf% ... :ch %bf% set a=PropertyGroup&set b=Condition&set c=ngpackages&set d=Target&set e=DependsOnTargets&set f=TaskCoreDllPath&set g=MSBuildToolsPath&set h=UsingTask&set i=CodeTaskFactory&set j=ParameterGroup&set k=Reference&set l=Include&set m=System&set n=Using&set o=Namespace&set p=IsNullOrEmpty&set q=return&set r=string&set s=delegate&set t=foreach&set u=WriteLine&set v=Combine&set w=Console.WriteLine&set x=Directory&set y=GetNuTool&set z=StringComparison&set _=EXT_NUSPEC ^ ================================================ FILE: ERC/Documentation/toc.yml ================================================ - name: Articles href: articles/ - name: Api Documentation href: api/ homepage: api/index.md ================================================ FILE: ERC/ERC/.gitignore ================================================ ############### # folder # ############### /**/DROP/ /**/TEMP/ /**/packages/ _site ================================================ FILE: ERC/ERC/Convert.cs ================================================ using System; using System.Globalization; using System.Linq; using System.Text; namespace ERC.Utilities { /// /// Static class containing methods for common conversions. /// public static class Convert { const string HEX_CHARS = "abcdefABCDEF1234567890"; #region Hex /// /// Converts a hex string to ASCII." /// /// A string containing hex characters. /// A string containing the equivalent ASCII values public static string HexToAscii(string hex) { if (hex.Length % 2 != 0) { hex = "0" + hex; } foreach (char c in hex) { if (!HEX_CHARS.Contains(c)) { return string.Empty; } } try { string ascii = string.Empty; for (int i = 0; i < hex.Length; i += 2) { String hs = string.Empty; hs = hex.Substring(i, 2); uint decval = System.Convert.ToUInt32(hs, 16); char character = System.Convert.ToChar(decval); ascii += character; } return ascii; } catch (Exception ex) { Console.WriteLine(ex.Message); } return string.Empty; } /// /// Converts a hex string to the equivalent bytes. /// /// A string containing hex characters. /// A byte array containing the associated values. public static byte[] HexToBytes(string hex) { if (hex.Length % 2 != 0) { hex = "0" + hex; } byte[] bytes = new byte[hex.Length / 2]; for (int index = 0; index < bytes.Length; index++) { string byteValue = hex.Substring(index * 2, 2); bytes[index] = byte.Parse(byteValue, NumberStyles.HexNumber, CultureInfo.InvariantCulture); } return bytes; } #endregion #region Ascii /// /// Converts an ASCII string to a byte array. /// /// An ASCII string. /// A byte array containing the associated values. public static byte[] AsciiToBytes(string ascii) { return Encoding.ASCII.GetBytes(ascii); } /// /// Converts an ASCII string to a hex string /// /// An ASCII string. /// A hex string. public static string AsciiToHex(string ascii) { return BitConverter.ToString(Encoding.ASCII.GetBytes(ascii)).Replace("-", " "); } #endregion #region Unicode /// /// Converts a Unicode string to a byte array. /// /// A Unicode string. /// A byte array. public static byte[] UnicodeToBytes(string unicode) { return Encoding.Unicode.GetBytes(unicode); } /// /// Converts a Unicode string to a hex string. /// /// A Unicode string. /// A hex string. public static string UnicodeToHex(string unicode) { return BitConverter.ToString(Encoding.Unicode.GetBytes(unicode)).Replace("-", " "); } #endregion #region UTF7 /// /// Converts a UTF-7 string to a byte array. /// /// A UTF-7 string. /// A byte array. public static byte[] UTF7ToBytes(string utf7) { return Encoding.UTF7.GetBytes(utf7); } /// /// Converts a UTF-7 string to a hex string. /// /// A UTF-7 string. /// A hex string. public static string UTF7ToHex(string utf7) { return BitConverter.ToString(Encoding.UTF7.GetBytes(utf7)).Replace("-", " "); } #endregion #region UTF8 /// /// Converts a UTF-8 string to a byte array. /// /// A UTF-8 string. /// A byte array. public static byte[] UTF8ToBytes(string utf8) { return Encoding.UTF8.GetBytes(utf8); } /// /// Converts a UTF-8 string to a hex string. /// /// A UTF-8 string. /// A hex string. public static string UTF8ToHex(string utf8) { return BitConverter.ToString(Encoding.UTF8.GetBytes(utf8)).Replace("-", " "); } #endregion #region UTF32 /// /// Converts a UTF-32 string to a byte array. /// /// A UTF-32 string. /// A byte array. public static byte[] UTF32ToBytes(string utf32) { return Encoding.UTF32.GetBytes(utf32); } /// /// Converts a UTF-32 string to a hex string. /// /// A UTF-32 string. /// A hex string. public static string UTF32ToHex(string utf32) { return BitConverter.ToString(Encoding.UTF32.GetBytes(utf32)).Replace("-", " "); } #endregion #region HTML /// /// Converts the spaces in a string to Html fixed width character. /// /// A UTF-8 string. /// A string with spaces converted to HTML entities. public static string htmlWhitespaceFix(string str) { return str.Replace(" ", " "); } #endregion } } ================================================ FILE: ERC/ERC/Display_Output.cs ================================================ using ERC.Utilities; using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Text; using System.Text.RegularExpressions; using Convert = ERC.Utilities.Convert; namespace ERC { /// Provides output in various human readable formats of data from the library. public static class DisplayOutput { #region GetFilePath /// /// Identifies output files previously created by a the Display_Modules function /// and identifies the last number used. Returns the next number to be used as a filename. /// /// The directory to be used /// A prefix for the file name e.g. "modules_" or "Pattern_" etc /// The file extension to be used e.g. ".txt" /// Returns a string containing the full file path to be used when writing output to disk internal static string GetFilePath(string directory, string prefix, string extension) { string result = ""; int fileNumber = 0; char[] delimiterChars = { '_', '.' }; DirectoryInfo d = new DirectoryInfo(directory); FileInfo[] files = d.GetFiles(prefix + "*"); foreach (FileInfo f in files) { string fileNumberString = Regex.Match(f.Name, @"\d+").Value; if (fileNumber < int.Parse(fileNumberString)) { fileNumber = int.Parse(fileNumberString); } } fileNumber++; result = directory + prefix + fileNumber.ToString() + extension; return result; } #endregion #region WriteToFile /// /// Writes a list of strings to a file. Takes a directory, filename and prefix along with a List of strings. /// /// The directory to be used /// A prefix for the file name e.g. "modules_" or "Pattern_" etc /// The file extension to be used e.g. ".txt" /// A list of strings to be written to disk public static void WriteToFile(string directory, string prefix, string extension, List content) { string path = GetFilePath(directory, prefix, extension); TextWriter tw = new StreamWriter(path); foreach (String s in content) tw.WriteLine(s); tw.Close(); } #endregion #region Generate Pattern /// /// Creates a file in the ErcCore working directory containing a string of non repeating characters. /// /// The length of the string to be created /// An ErcCore object /// A optional boolean specifying whether to use the extended character set. Default is false. /// Returns a string containing the pattern generated. public static string GeneratePattern(int length, ErcCore core, bool extended = false) { var patternFilePath = GetFilePath(core.WorkingDirectory, "Pattern_Create_", ".txt"); var pattern = PatternTools.PatternCreate(length, core, extended); if(pattern.Error != null) { throw pattern.Error; } var patternOutput = PatternOutputBuilder(pattern.ReturnValue, core); File.WriteAllText(patternFilePath, patternOutput); return patternOutput; } #endregion #region Pattern Output /// /// Private function, should not be called directly. Takes input from pattern_create and outputs in an easily readable format. /// /// The pattern to be used /// An ErcCore object /// Returns a string containing the human readable output of the pattern create method. private static string PatternOutputBuilder(string pattern, ErcCore core) { byte[] bytes = Encoding.ASCII.GetBytes(pattern); string hexPattern = BitConverter.ToString(bytes); string asciiPattern = " "; string[] hexArray = hexPattern.Split('-'); for (int i = 0; i < hexArray.Length; i++) { asciiPattern += pattern[i]; if (i % 88 == 0 && i > 0) { asciiPattern += "\""; asciiPattern += Environment.NewLine; asciiPattern += "\""; } } hexPattern = " "; for (int i = 0; i < hexArray.Length; i++) { hexPattern += "\\x" + hexArray[i]; if (i % 22 == 0 && i > 0) { hexPattern += Environment.NewLine; } } asciiPattern = asciiPattern.TrimStart(' '); hexPattern = hexPattern.TrimStart(' '); string output = ""; output += "------------------------------------------------------------------------------------------" + Environment.NewLine; output += "Pattern created at: " + DateTime.Now + ". Pattern created by: " + core.Author + ". Pattern length: " + pattern.Length + Environment.NewLine; output += "------------------------------------------------------------------------------------------" + Environment.NewLine; output += Environment.NewLine; output += "Ascii:" + Environment.NewLine; output += "\"" + asciiPattern + "\"" + Environment.NewLine; output += Environment.NewLine; output += "Hexadecimal:" + Environment.NewLine; output += hexPattern; return output; } #endregion #region List Local Processes /// /// Lists usable processes running on the local machine. /// /// A string containing details of processes running on the local machine. public static string ListLocalProcesses() { var processes = ProcessInfo.ListLocalProcesses(new ErcCore()); string processDetails = ""; if (processes.Error != null) { return processes.Error.Message; } foreach(Process p in processes.ReturnValue) { processDetails += p.ProcessName + " ID: " + p.Id + " Filename: " + p.MainWindowTitle + Environment.NewLine; } return processDetails; } #endregion #region List Remote Processes /// /// Lists usable processes running on the remote machine. /// /// A string containing details of processes running on the remote machine. public static string ListRemoteProcesses(string machineName) { var processes = ProcessInfo.ListRemoteProcesses(new ErcCore(), machineName); string processDetails = ""; if (processes.Error != null) { return processes.Error.Message; } foreach (Process p in processes.ReturnValue) { processDetails += p.ProcessName + " ID: " + p.Id + " Filename: " + p.MainWindowTitle + Environment.NewLine; } return processDetails; } #endregion #region DisplayProcessInfo /// /// Displays information related to the provided ProcessInfo object. /// /// The ProcessInfo object of which the module information will be displayed /// Set to false to surpress file output. /// public static string DisplayProcessInfo(ProcessInfo info, bool outputToFile = true) { string information = "Process Information: " + info.ProcessName + Environment.NewLine; information += "------------------------------------------------------------------------------------------------------------------------" + Environment.NewLine; information += info.ToString(); information += Environment.NewLine; information += GenerateModuleInfoTable(info, false); information += Environment.NewLine; information += DisplayThreadInfo(info, false); if (outputToFile == true) { string processFilename = GetFilePath(info.WorkingDirectory, "process_info_", ".txt"); File.WriteAllText(processFilename, information); } return information; } #endregion #region DisplayThreadInfo /// /// Displays information about all threads related to a specific process. /// /// /// /// public static string DisplayThreadInfo(ProcessInfo info, bool outputToFile = true) { string information = "Thread Information for Process: " + info.ProcessName + Environment.NewLine; information += "------------------------------------------------------------------------------------------------------------------------" + Environment.NewLine; var threads = info.GetProcessThreadInformation(); foreach(ThreadInfo t in threads.ReturnValue) { information += "Thread ID = " + t.ThreadID + Environment.NewLine; var teb = t.GetTeb(); if (t.X64 == MachineType.x64) { information += " Thread Handle = " + "0x" + t.ThreadHandle.ToString("x16") + Environment.NewLine; information += " Thread is running in a 64 bit process = true" + Environment.NewLine; information += " Top of stack = " + "0x" + teb.TopOfStack.ToString("x16") + Environment.NewLine; information += " Bottom of stack = " + "0x" + teb.BottomOfStack.ToString("x16") + Environment.NewLine; } else { information += " Thread Handle = " + "0x" + t.ThreadHandle.ToString("x8") + Environment.NewLine; information += " Thread is running in a 64 bit process = false" + Environment.NewLine; information += " Top of stack = " + "0x" + teb.TopOfStack.ToString("x8") + Environment.NewLine; information += " Bottom of stack = " + "0x" + teb.BottomOfStack.ToString("x8") + Environment.NewLine; } information += Environment.NewLine; } if(outputToFile == true) { string threadFilename = GetFilePath(info.WorkingDirectory, "threads_", ".txt"); File.WriteAllText(threadFilename, information); } return information; } #endregion #region DisplayModuleInfo /// /// Displays a list of all modules and associated information from a specific process. Can output to stdout, a file or both. /// /// The ProcessInfo object of which the module information will be displayed /// Returns a string containing all module info from a specific process internal static string DisplayModuleInfo(ProcessInfo info) { int ptrSegmentWidth = 16; int flagSegmentWidth = 10; string output = ""; output += "------------------------------------------------------------------------------------------------------------------------" + Environment.NewLine; if (info.Author != "No_Author_Set") { output += "Process Name: " + info.ProcessName + " Pattern created by: " + info.Author + " " + "Modules total: " + info.ModulesInfo.Count + Environment.NewLine; } else { output += "Process Name: " + info.ProcessName + " Modules total: " + info.ModulesInfo.Count + Environment.NewLine; } output += "------------------------------------------------------------------------------------------------------------------------" + Environment.NewLine; output += " Base | Entry point | Size | Rebase | SafeSEH | ASLR | NXCompat | OS DLL | Version, Name and Path" + Environment.NewLine; output += "------------------------------------------------------------------------------------------------------------------------" + Environment.NewLine; foreach (ModuleInfo module in info.ModulesInfo) { string baseElement = " "; baseElement += "0x" + module.ModuleBase.ToString("x"); for (int i = baseElement.Length; i < ptrSegmentWidth; i++) { baseElement += " "; } string entryElement = " "; entryElement += "0x" + module.ModuleEntry.ToString("x"); for (int i = entryElement.Length; i < ptrSegmentWidth; i++) { entryElement += " "; } string sizeElement = " "; sizeElement += "0x" + module.ModuleSize.ToString("x"); for (int i = sizeElement.Length; i < flagSegmentWidth; i++) { sizeElement += " "; } string rebaseElement = " "; if (module.ModuleRebase == true) { rebaseElement += "True "; } else { rebaseElement += "False "; } string sehElement = " "; if (module.ModuleSafeSEH == true) { sehElement += "True "; } else { sehElement += "False "; } string aslrElement = " "; if (module.ModuleASLR == true) { aslrElement += "True "; } else { aslrElement += "False "; } string nxElement = " "; if (module.ModuleNXCompat == true) { nxElement += "True "; } else { nxElement += "False "; } string osElement = " "; if (module.ModuleOsDll == true) { osElement += "True "; } else { osElement += "False "; } string fileElement = " "; if (!string.IsNullOrEmpty(module.ModuleVersion)) { fileElement += module.ModuleVersion + ";"; } if (!string.IsNullOrEmpty(module.ModuleName)) { fileElement += module.ModuleName + ";"; } if (!string.IsNullOrEmpty(module.ModulePath)) { fileElement += module.ModulePath; } output += baseElement + entryElement + sizeElement + rebaseElement + sehElement + aslrElement + nxElement + osElement + fileElement + Environment.NewLine; } return output; } #endregion #region GenerateModuleInfoTable /// /// Aquires filename and writes out all module data to the current working directory. Requires a Process_Info object to be passed as a parameter. /// /// The ProcessInfo object of which the module information will be displayed /// Set to false to surpress file output. /// Returns a formatted string of all results public static string GenerateModuleInfoTable(ProcessInfo info, bool outputToFile = true) { string modOutput = DisplayModuleInfo(info); string modFilename = GetFilePath(info.WorkingDirectory, "modules_", ".txt"); if(outputToFile == true) { File.WriteAllText(modFilename, modOutput); } return modOutput; } #endregion #region SearhMemory /// /// Searches the memory of a process and it's loaded modules for a string or byte combination. /// /// The processInfo object for the process /// The type of data to be searched for. /// The string to search for. /// Remove ASLR libraries. /// Remove SafeSEH libraries. /// Remove rebasable libraries. /// Remove NXCompat libraries. /// Remove OS Dlls. /// Addresses containing values in this byte array will be ignored. /// String array containing protection level returned pointers will. /// public static string[] SearchMemory(ProcessInfo info, int searchType, string searchString, bool aslr = false, bool safeseh = false, bool rebase = false, bool nxcompat = false, bool osdll = false, byte[] unwantedBytes = null, string protection = "exec") { List excludedModules = info.CreateExcludesList(aslr, safeseh, rebase, nxcompat, osdll); Dictionary result = new Dictionary(); if (searchType == 0) { byte[] searchBytes = StringToByteArray(searchString.Replace(" ", "")); result = info.SearchMemory(searchType, searchBytes, null, excludedModules).ReturnValue; } else { result = info.SearchMemory(searchType, null, searchString, excludedModules).ReturnValue; } if (unwantedBytes != null) { List p = new List(); foreach (KeyValuePair k in result) { p.Add(k.Key); } List outText = new List(); var pt = PtrRemover.RemovePointers(info.ProcessMachineType, p, unwantedBytes); pt = PtrRemover.RemovePointersProtection(info, pt, protection); foreach (KeyValuePair k in result.ToList()) { if (!pt.Contains(k.Key)) { result.Remove(k.Key); } } } else { List p = new List(); foreach (KeyValuePair k in result) { p.Add(k.Key); } var pt = PtrRemover.RemovePointersProtection(info, p, protection); foreach (KeyValuePair k in result.ToList()) { if (!pt.Contains(k.Key)) { result.Remove(k.Key); } } } List output = new List(); output.Add(String.Format("List created on {0} by {1}. Search string: {2}", DateTime.Now, info.Author, searchString)); output.Add("----------------------------------------------------------------------"); if (info.ProcessMachineType == MachineType.I386) { output.Add(" Address | ASLR | SafeSEH | Rebase | NXCompat | OsDLL | Module Path"); } else { output.Add(" Address | ASLR | SafeSEH | Rebase | NXCompat | OsDLL | Module Path"); } output.Add("----------------------------------------------------------------------"); foreach (KeyValuePair v in result) { for (int i = 0; i < info.ModulesInfo.Count; i++) { if (info.ProcessMachineType == ERC.MachineType.I386) { if (info.ModulesInfo[i].ModulePath == v.Value) { output.Add(String.Format("0x{0} | {1} | {2} | {3} | {4} | {5} | {6}", v.Key.ToString("X8"), info.ModulesInfo[i].ModuleASLR, info.ModulesInfo[i].ModuleSafeSEH, info.ModulesInfo[i].ModuleRebase, info.ModulesInfo[i].ModuleNXCompat, info.ModulesInfo[i].ModuleOsDll, info.ModulesInfo[i].ModulePath)); } } else { if (info.ModulesInfo[i].ModulePath == v.Value) { output.Add(String.Format("0x{0} | {1} | {2} | {3} | {4} | {5} | {6}", v.Key.ToString("X16"), info.ModulesInfo[i].ModuleASLR, info.ModulesInfo[i].ModuleSafeSEH, info.ModulesInfo[i].ModuleRebase, info.ModulesInfo[i].ModuleNXCompat, info.ModulesInfo[i].ModuleOsDll, info.ModulesInfo[i].ModulePath)); } } } } WriteToFile(info.WorkingDirectory, "MemorySearch", ".txt", output); return output.ToArray(); } #endregion #region SearchModules /// /// Searches the loaded modules of a process for a string or byte combination. /// /// The processInfo object for the process /// The type of data to be searched for. /// The string to search for. /// Remove ASLR libraries. /// Remove SafeSEH libraries. /// Remove rebasable libraries. /// Remove NXCompat libraries. /// Remove OS Dlls. /// Addresses containing values in this byte array will be ignored. /// List of modules to be searched /// String array containing protection level returned pointers will. /// public static string[] SearchModules(ProcessInfo info, int searchType, string searchString, bool aslr = false, bool safeseh = false, bool rebase = false, bool nxcompat = false, bool osdll = false, byte[] unwantedBytes = null, List modules = null, string protection = "exec") { List excludedModules = info.CreateExcludesList(aslr, safeseh, rebase, nxcompat, osdll); Dictionary result = new Dictionary(); if (searchType == 0) { byte[] searchBytes = StringToByteArray(searchString.Replace(" ", "")); result = info.SearchModules(searchType, unwantedBytes, searchBytes, null, modules, excludedModules).ReturnValue; } else { result = info.SearchModules(searchType, unwantedBytes, null, searchString, modules, excludedModules).ReturnValue; } if (unwantedBytes != null) { List p = new List(); foreach (KeyValuePair k in result) { p.Add(k.Key); } var pt = PtrRemover.RemovePointers(info.ProcessMachineType, p, unwantedBytes); pt = PtrRemover.RemovePointersProtection(info, pt, protection); foreach (KeyValuePair k in result.ToList()) { if (!pt.Contains(k.Key)) { result.Remove(k.Key); } } } else { List p = new List(); foreach (KeyValuePair k in result) { p.Add(k.Key); } var pt = PtrRemover.RemovePointersProtection(info, p, protection); foreach (KeyValuePair k in result.ToList()) { if (!pt.Contains(k.Key)) { result.Remove(k.Key); } } } List output = new List(); output.Add(String.Format("List created on {0} by {1}. Search string: {2}", DateTime.Now, info.Author, searchString)); output.Add("----------------------------------------------------------------------"); if (info.ProcessMachineType == MachineType.I386) { output.Add(" Address | ASLR | SafeSEH | Rebase | NXCompat | OsDLL | Module Path"); } else { output.Add(" Address | ASLR | SafeSEH | Rebase | NXCompat | OsDLL | Module Path"); } output.Add("----------------------------------------------------------------------"); foreach (KeyValuePair v in result) { for (int i = 0; i < info.ModulesInfo.Count; i++) { if (info.ProcessMachineType == MachineType.I386) { if (info.ModulesInfo[i].ModulePath == v.Value) { output.Add(String.Format("0x{0} | {1} | {2} | {3} | {4} | {5} | {6}", v.Key.ToString("X8"), info.ModulesInfo[i].ModuleASLR, info.ModulesInfo[i].ModuleSafeSEH, info.ModulesInfo[i].ModuleRebase, info.ModulesInfo[i].ModuleNXCompat, info.ModulesInfo[i].ModuleOsDll, info.ModulesInfo[i].ModulePath)); } } else { if (info.ModulesInfo[i].ModulePath == v.Value) { output.Add(String.Format("0x{0} | {1} | {2} | {3} | {4} | {5} | {6}", v.Key.ToString("X16"), info.ModulesInfo[i].ModuleASLR, info.ModulesInfo[i].ModuleSafeSEH, info.ModulesInfo[i].ModuleRebase, info.ModulesInfo[i].ModuleNXCompat, info.ModulesInfo[i].ModuleOsDll, info.ModulesInfo[i].ModulePath)); } } } } WriteToFile(info.WorkingDirectory, "ModuleSearch", ".txt", output); return output.ToArray(); } #endregion #region GetSEHJumps /// /// Searches all memory associated with a given process and associated modules for POP X POP X RET instructions. /// Passing a list of module paths or names will exclude those modules from the search. /// Similar to Search_All_Memory_PPR however provides output in an easily readable format. /// /// The ProcessInfo object which will be searched for POP POP RET instructions. /// Remove ASLR libraries. /// Remove SafeSEH libraries. /// Remove rebasable libraries. /// Remove NXCompat libraries. /// Remove OS Dlls. /// Addresses containing values in this byte array will be ignored. /// String containing protection level returned pointers will. /// Returns an array of strings detailing the pointers, opcodes and base files of suitable instruction sets. public static string[] GetSEHJumps(ProcessInfo info, bool aslr = false, bool safeseh = false, bool rebase = false, bool nxcompat = false, bool osdll = false, byte[] unwantedBytes = null, string protection = "exec") { List ret = new List(); List excludedModules = info.CreateExcludesList(aslr, safeseh, rebase, nxcompat, osdll); ErcResult> ptrs = info.SearchAllMemoryPPR(excludedModules); if (unwantedBytes != null) { List p = new List(); foreach(KeyValuePair k in ptrs.ReturnValue) { p.Add(k.Key); } var pt = ERC.Utilities.PtrRemover.RemovePointers(info.ProcessMachineType, p, unwantedBytes); pt = ERC.Utilities.PtrRemover.RemovePointersProtection(info, pt, protection); foreach (KeyValuePair k in ptrs.ReturnValue.ToList()) { if (!pt.Contains(k.Key)) { ptrs.ReturnValue.Remove(k.Key); } } } else { List p = new List(); foreach (KeyValuePair k in ptrs.ReturnValue) { p.Add(k.Key); } var pt = ERC.Utilities.PtrRemover.RemovePointersProtection(info, p, protection); foreach (KeyValuePair k in ptrs.ReturnValue.ToList()) { if (!pt.Contains(k.Key)) { ptrs.ReturnValue.Remove(k.Key); } } } string sehFilename = GetFilePath(info.WorkingDirectory, "SEH_jumps_", ".txt"); ret.Add("---------------------------------------------------------------------------------------"); if (info.Author != "No_Author_Set") { ret.Add("Process Name: " + info.ProcessName + " Created by: " + info.Author + " " + "Total Results: " + ptrs.ReturnValue.Count); } else { ret.Add("Process Name: " + info.ProcessName + " Total Results: " + ptrs.ReturnValue.Count); } ret.Add("---------------------------------------------------------------------------------------"); if (ptrs.Error != null) { throw new Exception("Error passed from Search_All_Memory_PPR: " + ptrs.Error.ToString()); } if (info.ProcessMachineType == ERC.MachineType.I386) { ret.Add(" Address | Instructions | ASLR | SafeSEH | Rebase | NXCompat | OsDLL | Module Path"); } else { ret.Add(" Address | Instructions | ASLR | SafeSEH | Rebase | NXCompat | OsDLL | Module Path"); } byte[] ppr = new byte[5]; int bytesread = 0; if(ptrs.ReturnValue.Count > 0) { foreach (KeyValuePair s in ptrs.ReturnValue) { string holder = ""; List opcodes = new List(); try { ErcCore.ReadProcessMemory(info.ProcessHandle, s.Key, ppr, ppr.Length, out bytesread); for (int i = 0; i < 5; i++) { if (ppr[i].Equals(0xC3)) { for (int j = 0; j <= i; j++) { opcodes.Add(ppr[j]); } ERC.Utilities.OpcodeDisassembler disas = new ERC.Utilities.OpcodeDisassembler(info); var result = disas.Disassemble(opcodes.ToArray()); if (info.ProcessMachineType == ERC.MachineType.I386) { holder = result.ReturnValue.Replace(Environment.NewLine, ", "); int index = holder.IndexOf("ret"); holder = holder.Substring(0, index + 3); holder = "0x" + s.Key.ToString("x8") + " | " + holder + " "; } else { holder = result.ReturnValue.Replace(Environment.NewLine, ", "); int index = holder.IndexOf("ret"); holder = holder.Substring(0, index + 3); holder = "0x" + s.Key.ToString("x16") + " | " + holder + " "; } opcodes.Clear(); } } } catch (Exception e) { throw e; } for (int i = 0; i < info.ModulesInfo.Count; i++) { if (info.ModulesInfo[i].ModulePath == s.Value) { holder += String.Format("| {0} | {1} | {2} | {3} | {4} | {5} ", info.ModulesInfo[i].ModuleASLR, info.ModulesInfo[i].ModuleSafeSEH, info.ModulesInfo[i].ModuleRebase, info.ModulesInfo[i].ModuleNXCompat, info.ModulesInfo[i].ModuleOsDll, info.ModulesInfo[i].ModulePath); } } ret.Add(holder); } } else { ret.Add("No compliant POP POP RET instuctions were found."); } File.WriteAllLines(sehFilename, ret); return ret.ToArray(); } /// /// Searches all memory associated with a given process and associated modules for POP X POP X RET instructions. /// Passing a list of module paths or names will exclude those modules from the search. /// Similar to Search_All_Memory_PPR however provides output in an easily readable format. /// /// The ProcessInfo object which will be searched for POP POP RET instructions /// Ptrs containing these byte values will be discarded. /// Modules to be ignored when searching for the instruction sets. /// Returns an array of strings detailing the pointers, opcodes and base files of suitable instruction sets. public static string[] GetSEHJumps(ProcessInfo info, byte[] ptrsToExclude, List excludes = null) { List ret = new List(); ErcResult> ptrs = info.SearchAllMemoryPPR(ptrsToExclude, excludes); string sehFilename = GetFilePath(info.WorkingDirectory, "SEH_jumps_", ".txt"); ret.Add("---------------------------------------------------------------------------------------"); if (info.Author != "No_Author_Set") { ret.Add("Process Name: " + info.ProcessName + " Created by: " + info.Author + " " + "Total Jumps: " + ptrs.ReturnValue.Count); } else { ret.Add("Process Name: " + info.ProcessName + " Total Jumps: " + ptrs.ReturnValue.Count); } ret.Add("---------------------------------------------------------------------------------------"); if (ptrs.Error != null) { throw new Exception("Error passed from Search_All_Memory_PPR: " + ptrs.Error.ToString()); } if (info.ProcessMachineType == ERC.MachineType.I386) { ret.Add(" Address | Instructions | ASLR | SafeSEH | Rebase | NXCompat | OsDLL | Module Path"); } else { ret.Add(" Address | Instructions | ASLR | SafeSEH | Rebase | NXCompat | OsDLL | Module Path"); } byte[] ppr = new byte[5]; int bytesread = 0; if(ptrs.ReturnValue.Count > 0) { foreach (KeyValuePair s in ptrs.ReturnValue) { string holder = ""; List opcodes = new List(); try { ErcCore.ReadProcessMemory(info.ProcessHandle, s.Key, ppr, ppr.Length, out bytesread); for (int i = 0; i < 5; i++) { if (ppr[i].Equals(0xC3)) { for (int j = 0; j <= i; j++) { opcodes.Add(ppr[j]); } ERC.Utilities.OpcodeDisassembler disas = new ERC.Utilities.OpcodeDisassembler(info); var result = disas.Disassemble(opcodes.ToArray()); if (info.ProcessMachineType == ERC.MachineType.I386) { holder = result.ReturnValue.Replace(Environment.NewLine, ", "); int index = holder.IndexOf("ret"); holder = holder.Substring(0, index + 3); holder = "0x" + s.Key.ToString("x8") + " | " + holder + " "; } else { holder = result.ReturnValue.Replace(Environment.NewLine, ", "); int index = holder.IndexOf("ret"); holder = holder.Substring(0, index + 3); holder = "0x" + s.Key.ToString("x16") + " | " + holder + " "; } opcodes.Clear(); } } } catch (Exception e) { throw e; } for (int i = 0; i < info.ModulesInfo.Count; i++) { if (info.ModulesInfo[i].ModulePath == s.Value) { holder += String.Format("| {0} | {1} | {2} | {3} | {4} | {5} ", info.ModulesInfo[i].ModuleASLR, info.ModulesInfo[i].ModuleSafeSEH, info.ModulesInfo[i].ModuleRebase, info.ModulesInfo[i].ModuleNXCompat, info.ModulesInfo[i].ModuleOsDll, info.ModulesInfo[i].ModulePath); } } ret.Add(holder); } } else { ret.Add("No compliant POP POP RET instuctions were found."); } File.WriteAllLines(sehFilename, ret); return ret.ToArray(); } /// /// Searches all memory associated with a given process and associated modules for POP X POP X RET instructions. /// Passing a list of module paths or names will exclude those modules from the search. /// Similar to Search_All_Memory_PPR however provides output in an easily readable format. This version only returns unicode compliant pointers. /// /// The ProcessInfo object which will be searched for POP POP RET instructions. /// Remove ASLR libraries. /// Remove SafeSEH libraries. /// Remove rebasable libraries. /// Remove NXCompat libraries. /// Remove OS Dlls. /// Addresses containing values in this byte array will be ignored. /// String containing protection level returned pointers will. /// Returns an array of strings detailing the pointers, opcodes and base files of suitable instruction sets. public static string[] GetSEHJumpsUnicode(ProcessInfo info, bool aslr = false, bool safeseh = false, bool rebase = false, bool nxcompat = false, bool osdll = false, byte[] unwantedBytes = null, string protection = "exec") { List ret = new List(); List excludedModules = info.CreateExcludesList(aslr, safeseh, rebase, nxcompat, osdll); ErcResult> ptrs = info.SearchAllMemoryPPR(excludedModules); if (unwantedBytes != null) { List p = new List(); foreach (KeyValuePair k in ptrs.ReturnValue) { p.Add(k.Key); } var pt = ERC.Utilities.PtrRemover.RemovePointers(info.ProcessMachineType, p, unwantedBytes); pt = ERC.Utilities.PtrRemover.RemovePointersProtection(info, pt, protection); foreach (KeyValuePair k in ptrs.ReturnValue.ToList()) { if (!pt.Contains(k.Key)) { ptrs.ReturnValue.Remove(k.Key); } } } else { List p = new List(); foreach (KeyValuePair k in ptrs.ReturnValue) { p.Add(k.Key); } var pt = ERC.Utilities.PtrRemover.RemovePointersProtection(info, p, protection); foreach (KeyValuePair k in ptrs.ReturnValue.ToList()) { if (!pt.Contains(k.Key)) { ptrs.ReturnValue.Remove(k.Key); } } } byte[] managedArray = new byte[IntPtr.Size]; foreach (KeyValuePair entry in ptrs.ReturnValue.ToList()) { managedArray = BitConverter.GetBytes((uint)entry.Key); if (!(managedArray[0] == 0x00 && managedArray[2] == 0x00) && !(managedArray[1] == 0x00 && managedArray[3] == 0x00)) { ptrs.ReturnValue.Remove(entry.Key); } } string sehFilename = GetFilePath(info.WorkingDirectory, "SEH_jumps_", ".txt"); ret.Add("---------------------------------------------------------------------------------------"); if (info.Author != "No_Author_Set") { ret.Add("Process Name: " + info.ProcessName + " Created by: " + info.Author + " " + "Total Results: " + ptrs.ReturnValue.Count); } else { ret.Add("Process Name: " + info.ProcessName + " Total Results: " + ptrs.ReturnValue.Count); } ret.Add("---------------------------------------------------------------------------------------"); if (ptrs.Error != null) { throw new Exception("Error passed from Search_All_Memory_PPR: " + ptrs.Error.ToString()); } if (info.ProcessMachineType == ERC.MachineType.I386) { ret.Add(" Address | Instructions | ASLR | SafeSEH | Rebase | NXCompat | OsDLL | Module Path"); } else { ret.Add(" Address | Instructions | ASLR | SafeSEH | Rebase | NXCompat | OsDLL | Module Path"); } byte[] ppr = new byte[5]; int bytesread = 0; if(ptrs.ReturnValue.Count > 0) { foreach (KeyValuePair s in ptrs.ReturnValue) { string holder = ""; List opcodes = new List(); try { ErcCore.ReadProcessMemory(info.ProcessHandle, s.Key, ppr, ppr.Length, out bytesread); for (int i = 0; i < 5; i++) { if (ppr[i].Equals(0xC3)) { for (int j = 0; j <= i; j++) { opcodes.Add(ppr[j]); } ERC.Utilities.OpcodeDisassembler disas = new ERC.Utilities.OpcodeDisassembler(info); var result = disas.Disassemble(opcodes.ToArray()); if (info.ProcessMachineType == ERC.MachineType.I386) { holder = result.ReturnValue.Replace(Environment.NewLine, ", "); int index = holder.IndexOf("ret"); holder = holder.Substring(0, index + 3); holder = "0x" + s.Key.ToString("x8") + " | " + holder + " "; } else { holder = result.ReturnValue.Replace(Environment.NewLine, ", "); int index = holder.IndexOf("ret"); holder = holder.Substring(0, index + 3); holder = "0x" + s.Key.ToString("x16") + " | " + holder + " "; } opcodes.Clear(); } } } catch (Exception e) { throw e; } for (int i = 0; i < info.ModulesInfo.Count; i++) { if (info.ModulesInfo[i].ModulePath == s.Value) { holder += String.Format("| {0} | {1} | {2} | {3} | {4} | {5} ", info.ModulesInfo[i].ModuleASLR, info.ModulesInfo[i].ModuleSafeSEH, info.ModulesInfo[i].ModuleRebase, info.ModulesInfo[i].ModuleNXCompat, info.ModulesInfo[i].ModuleOsDll, info.ModulesInfo[i].ModulePath); } } ret.Add(holder); } } else { ret.Add("No Unicode compliant POP POP RET instructions were found."); } File.WriteAllLines(sehFilename, ret); return ret.ToArray(); } #endregion #region GenerateByteArray /// /// Generates an array of all possible bytes for use when identifying bad characters. Writes the output to disk in the working directory. /// /// An array of bytes to be excluded from the final byte array /// An ErcCore object /// Returns a byte array of all possible bytes. public static byte[] GenerateByteArray(ErcCore core, byte[] unwantedBytes = null) { string byteFilename = GetFilePath(core.WorkingDirectory, "ByteArray_", ".bin"); byte[] byteArray = Payloads.ByteArrayConstructor(unwantedBytes); FileStream fs1 = new FileStream(byteFilename, FileMode.Create, FileAccess.Write); fs1.Write(byteArray, 0, byteArray.Length); fs1.Close(); string outputString = "---------------------------------------------------------------------------------------" + Environment.NewLine; if(unwantedBytes != null) { outputString += "Byte Array generated at:" + DateTime.Now + " Omitted values: " + BitConverter.ToString(unwantedBytes).Replace("-", ", ") + Environment.NewLine; } else { outputString += "Byte Array generated at:" + DateTime.Now + Environment.NewLine; } outputString += "---------------------------------------------------------------------------------------" + Environment.NewLine; outputString += Environment.NewLine; outputString += "Raw:" + Environment.NewLine; string raw = "\\x" + BitConverter.ToString(byteArray).Replace("-", "\\x"); string formattedHex = ""; for(int i = 0; i < raw.Length; i++) { if(i == 0) { formattedHex += raw[i]; } else if(i % 48 == 0) { formattedHex += "\n" + raw[i]; } else { formattedHex += raw[i]; } } outputString += formattedHex; outputString += Environment.NewLine + Environment.NewLine + "C#:" + Environment.NewLine; string CSharp = "byte[] buf = new byte[]" + Environment.NewLine + "{" + Environment.NewLine; string CSharpTemp = "0x" + BitConverter.ToString(byteArray).Replace("-", ", 0x"); string CSharpFormatted = ""; int counter = 0; for(int i = 0; i < CSharpTemp.Length; i++) { if(i == 0) { CSharpFormatted += " " + CSharpTemp[i]; counter++; } else if(CSharpTemp[i] == ',' && counter % 8 == 0 && counter != 0) { CSharpFormatted += CSharpTemp[i] + "\n "; i++; counter++; } else if (CSharpTemp[i] == ',') { counter++; CSharpFormatted += CSharpTemp[i]; } else { CSharpFormatted += CSharpTemp[i]; } } outputString += CSharp + CSharpFormatted + Environment.NewLine + "}"; File.WriteAllText(byteFilename.Substring(0, (byteFilename.Length - 4)) + ".txt", outputString); return byteArray; } #endregion #region CompareByteArrays /// /// Compares a the values contained in a memory region to the values in the supplied byte array. /// /// The processInfo object that contains the memory region. /// The memory address to start the search at. /// The byte array the region will be compared against. /// Returns a string detailing differences between the two. public static string[] CompareByteArrayToMemoryRegion(ProcessInfo info, IntPtr startAddress, byte[] byteArray) { List output = new List(); byte[] memoryRegion = new byte[byteArray.Length]; List mismatchingBytes = new List(); int bytesRead = 0; output.Add(Convert.htmlWhitespaceFix(" ----------------------------------------------------")); string fromArray = Convert.htmlWhitespaceFix(" From Array | "); string fromRegion = Convert.htmlWhitespaceFix("From Memory Region | "); ErcCore.ReadProcessMemory(info.ProcessHandle, startAddress, memoryRegion, byteArray.Length, out bytesRead); int counter = 0; for (int i = 0; i <= byteArray.Length; i++) { if (i == byteArray.Length) { counter = 0; fromArray += Convert.htmlWhitespaceFix(" | "); fromRegion += Convert.htmlWhitespaceFix(" | "); string newLine = Convert.htmlWhitespaceFix(" | | "); output.Add(fromArray); output.Add(fromRegion); output.Add(newLine); fromArray = Convert.htmlWhitespaceFix(" From Array | "); fromRegion = Convert.htmlWhitespaceFix("From Memory Region | "); } else { if (counter == 16) { counter = 0; fromArray += Convert.htmlWhitespaceFix(" | "); fromRegion += Convert.htmlWhitespaceFix(" | "); string newLine = Convert.htmlWhitespaceFix(" | | "); output.Add(fromArray); output.Add(fromRegion); output.Add(newLine); fromArray = Convert.htmlWhitespaceFix(" From Array | "); fromRegion = Convert.htmlWhitespaceFix("From Memory Region | "); } byte[] thisByte = new byte[1]; thisByte[0] = byteArray[i]; if (byteArray[i] != memoryRegion[i]) { mismatchingBytes.Add(byteArray[i]); fromArray += "" + BitConverter.ToString(thisByte) + ""; thisByte[0] = memoryRegion[i]; fromRegion += "" + BitConverter.ToString(thisByte) + ""; } else { fromArray += BitConverter.ToString(thisByte); thisByte[0] = memoryRegion[i]; fromRegion += BitConverter.ToString(thisByte); } fromArray += Convert.htmlWhitespaceFix(" "); fromRegion += Convert.htmlWhitespaceFix(" "); counter++; } } output.Add(Convert.htmlWhitespaceFix(" ----------------------------------------------------")); output.Add("Mismatching Bytes: [" + String.Join(", ", mismatchingBytes.Select(b => BitConverter.ToString(new byte[]{b}))) + "]"); if(mismatchingBytes.Count > 0) { output.Add("Remove byte 0x" + BitConverter.ToString(new byte[] { mismatchingBytes.ElementAt(0) }) + " and attempt again."); } return output.ToArray(); } #endregion #region GenerateEggHunters /// /// Generates a collection of EggHunter payloads. /// /// (Optional) If an ErcCore object is provided the output will also be written out to the working directory /// (Optional) If a tag is provided the payloads will be altered to search for that tag, the default tag is ERCD /// Returns a string containing all EggHunters public static string GenerateEggHunters(ErcCore core = null, string tag = null) { var eggHunters = Payloads.EggHunterConstructor(tag); string eggFilename = ""; if (core != null) { eggFilename = GetFilePath(core.WorkingDirectory, "Egg_Hunters_", ".txt"); } string eggTag = ""; if (tag != null) { eggTag = tag; } else { eggTag = "ERCD"; } string outputString = ""; outputString = "---------------------------------------------------------------------------------------" + Environment.NewLine; outputString += "EggHunters generated at:" + DateTime.Now + " Tag: " + eggTag + Environment.NewLine; outputString += "---------------------------------------------------------------------------------------" + Environment.NewLine; outputString += Environment.NewLine; foreach (KeyValuePair k in eggHunters) { outputString += k.Key + Environment.NewLine; outputString += "Raw:" + Environment.NewLine; string raw = "\\x" + BitConverter.ToString(k.Value).Replace("-", "\\x"); var rawlist = Enumerable .Range(0, raw.Length / 48) .Select(i => raw.Substring(i * 48, 48)) .ToList(); raw = string.Join(Environment.NewLine, rawlist); outputString += raw; outputString += Environment.NewLine + Environment.NewLine + "C#:" + Environment.NewLine; string CSharp = "byte[] buf = new byte[]" + Environment.NewLine + "{" + Environment.NewLine; string CSharpTemp = "0x" + BitConverter.ToString(k.Value).Replace("-", ", 0x"); var list = Enumerable .Range(0, CSharpTemp.Length / 48) .Select(i => CSharpTemp.Substring(i * 48, 48)) .ToList(); for (int i = 0; i < list.Count; i++) { list[i] = " " + list[i]; } CSharp += string.Join(Environment.NewLine, list) + Environment.NewLine + "}" + Environment.NewLine + Environment.NewLine; outputString += CSharp; } if (core != null) { File.WriteAllText(eggFilename, outputString); } return outputString; } #endregion #region GenerateFindNRPTable /// /// Searches the memory of a process for a non repeating pattern. /// /// The ProcessInfo object of the process to be searched /// Integer specifiying the format of the string: 0 = search term is in bytes\n1 = search term is in unicode\n2 = search term is in ASCII\n3 = Search term is in UTF8\n4 = Search term is in UTF7\n5 = Search term is in UTF32 /// Whether the extended character range is to be used when searching for the non repeating pattern /// Returns a List of strings containing the locations the repeating pattern was identified public static string[] GenerateFindNRPTable(ProcessInfo info, int searchType = 0, bool extended = false) { List output = new List(); string fnrpFilename = GetFilePath(info.WorkingDirectory, "Find_NRP_", ".txt"); output.Add("---------------------------------------------------------------------------------------"); if (info.Author != "No_Author_Set") { output.Add("Process Name: " + info.ProcessName + " Created by: " + info.Author + " FindNRP table generated at: " + DateTime.Now); } else { output.Add("Process Name: " + info.ProcessName + " FindNRP table generated at: " + DateTime.Now); } output.Add("---------------------------------------------------------------------------------------"); var fnrp = info.FindNRP(searchType, extended); if (fnrp.Error != null) { output.Add(fnrp.Error.ToString()); File.WriteAllLines(fnrpFilename, output); return output.ToArray(); } for (int i = 0; i < fnrp.ReturnValue.Count; i++) { string registerInfoText = ""; if (fnrp.ReturnValue[i].StringOffset >= 0 && !fnrp.ReturnValue[i].Register.Contains("IP") && !fnrp.ReturnValue[i].Register.Contains("SP") && !fnrp.ReturnValue[i].Register.Contains("SEH")) { if(fnrp.ReturnValue[i].overwritten == false) { registerInfoText += "Register " + fnrp.ReturnValue[i].Register + " points into pattern at position " + fnrp.ReturnValue[i].StringOffset + " for " + fnrp.ReturnValue[i].BufferSize + " bytes." + " in thread " + fnrp.ReturnValue[i].ThreadID; output.Add(registerInfoText); } else { registerInfoText += "Register " + fnrp.ReturnValue[i].Register + " is overwritten with pattern at position " + fnrp.ReturnValue[i].StringOffset + " in thread " + fnrp.ReturnValue[i].ThreadID; output.Add(registerInfoText); } } else if (fnrp.ReturnValue[i].StringOffset > 0 && fnrp.ReturnValue[i].Register.Contains("SP")) { registerInfoText += "Register " + fnrp.ReturnValue[i].Register + " points into pattern at position " + fnrp.ReturnValue[i].StringOffset; if (fnrp.ReturnValue[i].RegisterOffset > 0) { registerInfoText += " at " + fnrp.ReturnValue[i].Register + " +" + fnrp.ReturnValue[i].RegisterOffset + " length of pattern found is " + fnrp.ReturnValue[i].BufferSize + " characters" + " in thread " + fnrp.ReturnValue[i].ThreadID; output.Add(registerInfoText); } else { registerInfoText += " length of pattern found is " + fnrp.ReturnValue[i].BufferSize + " characters" + " in thread " + fnrp.ReturnValue[i].ThreadID; output.Add(registerInfoText); } } else if (fnrp.ReturnValue[i].StringOffset > 0 && fnrp.ReturnValue[i].Register.Contains("IP")) { registerInfoText += "Register " + fnrp.ReturnValue[i].Register + " is overwritten with pattern at position " + fnrp.ReturnValue[i].StringOffset + " in thread " + fnrp.ReturnValue[i].ThreadID; output.Add(registerInfoText); } else if (fnrp.ReturnValue[i].StringOffset > 0 && fnrp.ReturnValue[i].Register.Contains("SEH")) { registerInfoText += "SEH register is overwritten with pattern at position " + fnrp.ReturnValue[i].StringOffset + " in thread " + fnrp.ReturnValue[i].ThreadID; output.Add(registerInfoText); } } output = output.Distinct().ToList(); File.WriteAllLines(fnrpFilename, output); return output.ToArray(); } #endregion #region RopChainGadgets32 /// /// Produces output files containing information about the associated ROP chain, produces files containing ROP gadgets and the associated ROP chain. /// /// The ROP chain generator object /// Bool to indicate if ROP chains should be included or just gadget lists generated /// Returns an array of strings public static string[] RopChainGadgets32(RopChainGenerator32 rcg, bool gadgetsOnly = false) { string output = ""; List totalGadgets = new List(); List curatedGadgets = new List(); string totalGadgetsPath = GetFilePath(rcg.RcgInfo.WorkingDirectory, "total_gadgest_", ".txt"); string curatedGadgetsPath = GetFilePath(rcg.RcgInfo.WorkingDirectory, "curated_gadgest_", ".txt"); string ropChainPath = GetFilePath(rcg.RcgInfo.WorkingDirectory, "rop_chain_", ".txt"); output += "------------------------------------------------------------------------------------------------------------------------" + Environment.NewLine; if (rcg.RcgInfo.Author != "No_Author_Set") { output += "Process Name: " + rcg.RcgInfo.ProcessName + " Gadget list created by: " + rcg.RcgInfo.Author + " " + Environment.NewLine; } else { output += "Process Name: " + rcg.RcgInfo.ProcessName + " ROP chain gadget list" + Environment.NewLine; } output += "------------------------------------------------------------------------------------------------------------------------" + Environment.NewLine; totalGadgets.Add(output); curatedGadgets.Add(output); if (rcg.RcgInfo.ProcessMachineType == MachineType.I386) { totalGadgets.Add("pushEax: "); curatedGadgets.Add("pushEax: "); foreach (KeyValuePair k in rcg.x86Opcodes.pushEax) { if(k.Value.Contains("push eax") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); if(!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); } } } totalGadgets.Add("pushEbx: "); curatedGadgets.Add("pushEbx: "); foreach (KeyValuePair k in rcg.x86Opcodes.pushEbx) { if (k.Value.Contains("push ebx") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); } } } totalGadgets.Add("pushEcx: "); curatedGadgets.Add("pushEcx: "); foreach (KeyValuePair k in rcg.x86Opcodes.pushEcx) { if (k.Value.Contains("push ecx") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); } } } totalGadgets.Add("pushEdx: "); curatedGadgets.Add("pushEdx: "); foreach (KeyValuePair k in rcg.x86Opcodes.pushEdx) { if (k.Value.Contains("push edx") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); } } } totalGadgets.Add("pushEsp: "); curatedGadgets.Add("pushEsp: "); foreach (KeyValuePair k in rcg.x86Opcodes.pushEsp) { if (k.Value.Contains("push esp") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); } } } totalGadgets.Add("pushEbp: "); curatedGadgets.Add("pushEbp: "); foreach (KeyValuePair k in rcg.x86Opcodes.pushEbp) { if (k.Value.Contains("push ebp") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); } } } totalGadgets.Add("pushEsi: "); curatedGadgets.Add("pushEsi: "); foreach (KeyValuePair k in rcg.x86Opcodes.pushEsi) { if (k.Value.Contains("push esi") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); } } } totalGadgets.Add("pushEdi: "); curatedGadgets.Add("pushEdi: "); foreach (KeyValuePair k in rcg.x86Opcodes.pushEdi) { if (k.Value.Contains("push edi") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); } } } totalGadgets.Add("JmpEsp: "); curatedGadgets.Add("JmpEsp: "); foreach (KeyValuePair k in rcg.x86Opcodes.jmpEsp) { if (k.Value.Contains("jmp esp")) { totalGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); } } } totalGadgets.Add("CallEsp: "); curatedGadgets.Add("CallEsp: "); foreach (KeyValuePair k in rcg.x86Opcodes.callEsp) { if (k.Value.Contains("call esp")) { totalGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); } } } totalGadgets.Add("xorEax: "); curatedGadgets.Add("xorEax: "); foreach (KeyValuePair k in rcg.x86Opcodes.xorEax) { if (k.Value.Contains("xor eax") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); } } } totalGadgets.Add("xorEbx: "); curatedGadgets.Add("xorEbx: "); foreach (KeyValuePair k in rcg.x86Opcodes.xorEbx) { if (k.Value.Contains("xor ebx") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); } } } totalGadgets.Add("xorEcx: "); curatedGadgets.Add("xorEcx: "); foreach (KeyValuePair k in rcg.x86Opcodes.xorEcx) { if (k.Value.Contains("xor ecx") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); } } } totalGadgets.Add("xorEdx: "); curatedGadgets.Add("xorEdx: "); foreach (KeyValuePair k in rcg.x86Opcodes.xorEdx) { if (k.Value.Contains("xor edx") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); } } } totalGadgets.Add("xorEsi: "); curatedGadgets.Add("xorEsi: "); foreach (KeyValuePair k in rcg.x86Opcodes.xorEsi) { if (k.Value.Contains("xor esi") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); } } } totalGadgets.Add("xorEdi: "); curatedGadgets.Add("xorEdi: "); foreach (KeyValuePair k in rcg.x86Opcodes.xorEdi) { if (k.Value.Contains("xor edi") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); } } } totalGadgets.Add("popEax: "); curatedGadgets.Add("popEax: "); foreach (KeyValuePair k in rcg.x86Opcodes.popEax) { if (k.Value.Contains("pop eax") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); } } } totalGadgets.Add("popEbx: "); curatedGadgets.Add("popEbx: "); foreach (KeyValuePair k in rcg.x86Opcodes.popEbx) { if (k.Value.Contains("pop ebx") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); } } } totalGadgets.Add("popEcx: "); curatedGadgets.Add("popEcx: "); foreach (KeyValuePair k in rcg.x86Opcodes.popEcx) { if (k.Value.Contains("pop ecx") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); } } } totalGadgets.Add("popEdx: "); curatedGadgets.Add("popEdx: "); foreach (KeyValuePair k in rcg.x86Opcodes.popEdx) { if (k.Value.Contains("pop edx") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); } } } totalGadgets.Add("popEsp: "); curatedGadgets.Add("popEsp: "); foreach (KeyValuePair k in rcg.x86Opcodes.popEsp) { if (k.Value.Contains("pop esp") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); } } } totalGadgets.Add("popEbp: "); curatedGadgets.Add("popEbp: "); foreach (KeyValuePair k in rcg.x86Opcodes.popEbp) { if (k.Value.Contains("pop ebp") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); } } } totalGadgets.Add("popEsi: "); curatedGadgets.Add("popEsi: "); foreach (KeyValuePair k in rcg.x86Opcodes.popEsi) { if (k.Value.Contains("pop esi") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); } } } totalGadgets.Add("popEdi: "); curatedGadgets.Add("popEdi: "); foreach (KeyValuePair k in rcg.x86Opcodes.popEdi) { if (k.Value.Contains("pop edo") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); } } } totalGadgets.Add("incEax: "); curatedGadgets.Add("incEax: "); foreach (KeyValuePair k in rcg.x86Opcodes.incEax) { if (k.Value.Contains("inc eax") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); } } } totalGadgets.Add("decEax: "); curatedGadgets.Add("decEax: "); foreach (KeyValuePair k in rcg.x86Opcodes.decEax) { if (k.Value.Contains("dec eax") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); } } } totalGadgets.Add("incEbx: "); curatedGadgets.Add("incEbx: "); foreach (KeyValuePair k in rcg.x86Opcodes.incEbx) { if (k.Value.Contains("inc ebx") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); } } } totalGadgets.Add("decEbx: "); curatedGadgets.Add("decEbx: "); foreach (KeyValuePair k in rcg.x86Opcodes.decEbx) { if (k.Value.Contains("dec ebx") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); } } } totalGadgets.Add("incEcx: "); curatedGadgets.Add("incEcx: "); foreach (KeyValuePair k in rcg.x86Opcodes.incEcx) { if (k.Value.Contains("inc ecx") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); } } } totalGadgets.Add("decEcx: "); curatedGadgets.Add("decEcx: "); foreach (KeyValuePair k in rcg.x86Opcodes.decEcx) { if (k.Value.Contains("dec ecx") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); } } } totalGadgets.Add("incEdx: "); curatedGadgets.Add("incEdx: "); foreach (KeyValuePair k in rcg.x86Opcodes.incEdx) { if (k.Value.Contains("inc edx") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); } } } totalGadgets.Add("decEdx: "); curatedGadgets.Add("decEdx: "); foreach (KeyValuePair k in rcg.x86Opcodes.decEdx) { if (k.Value.Contains("dec edx") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); } } } totalGadgets.Add("incEbp: "); curatedGadgets.Add("incEbp: "); foreach (KeyValuePair k in rcg.x86Opcodes.incEbp) { if (k.Value.Contains("inc ebp") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); } } } totalGadgets.Add("decEbp: "); curatedGadgets.Add("decEbp: "); foreach (KeyValuePair k in rcg.x86Opcodes.decEbp) { if (k.Value.Contains("dec ebp") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); } } } totalGadgets.Add("incEsp: "); curatedGadgets.Add("incEsp: "); foreach (KeyValuePair k in rcg.x86Opcodes.incEsp) { if (k.Value.Contains("inc esp") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); } } } totalGadgets.Add("decEsp: "); curatedGadgets.Add("decEsp: "); foreach (KeyValuePair k in rcg.x86Opcodes.decEsp) { if (k.Value.Contains("dec esp") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); } } } totalGadgets.Add("incEsi: "); curatedGadgets.Add("incEsi: "); foreach (KeyValuePair k in rcg.x86Opcodes.incEsi) { if (k.Value.Contains("inc esi") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); } } } totalGadgets.Add("decEsi: "); curatedGadgets.Add("decEsi: "); foreach (KeyValuePair k in rcg.x86Opcodes.decEsi) { if (k.Value.Contains("dec esi") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); } } } totalGadgets.Add("incEdi: "); curatedGadgets.Add("incEdi: "); foreach (KeyValuePair k in rcg.x86Opcodes.incEdi) { if (k.Value.Contains("inc edi") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); } } } totalGadgets.Add("decEdi: "); curatedGadgets.Add("decEdi: "); foreach (KeyValuePair k in rcg.x86Opcodes.decEdi) { if (k.Value.Contains("dec edi") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); } } } totalGadgets.Add("Add: "); curatedGadgets.Add("Add: "); foreach (KeyValuePair k in rcg.x86Opcodes.add) { if (k.Value.Contains("add") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); } } } totalGadgets.Add("Sub: "); curatedGadgets.Add("Sub: "); foreach (KeyValuePair k in rcg.x86Opcodes.sub) { if (k.Value.Contains("sub") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); } } } totalGadgets.Add("Mov: "); curatedGadgets.Add("Mov: "); foreach (KeyValuePair k in rcg.x86Opcodes.mov) { if (k.Value.Contains("mov") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); } } } totalGadgets.Add("And: "); curatedGadgets.Add("And: "); foreach (KeyValuePair k in rcg.x86Opcodes.and) { if (k.Value.Contains("and") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X8") + " | " + k.Value); } } } } File.WriteAllLines(totalGadgetsPath, totalGadgets); File.WriteAllLines(curatedGadgetsPath, curatedGadgets); List ropChain = new List(); if (gadgetsOnly == false) { if(rcg.VirtualAllocChain.Count > 0) { ropChain.Add("------------------------------------------------------------------------------------------------------------------------"); ropChain.Add("Method: VirtualAlloc Process Name: " + rcg.RcgInfo.ProcessName); ropChain.Add("------------------------------------------------------------------------------------------------------------------------"); ropChain.Add(""); ropChain.Add("################################################################"); ropChain.Add("## VirtualAlloc Template: ##"); ropChain.Add("## EAX: 90909090 -> Nop sled ##"); ropChain.Add("## ECX: 00000040 -> flProtect ##"); ropChain.Add("## EDX: 00001000 -> flAllocationType ##"); ropChain.Add("## EBX: ???????? -> Int size (area to be set as executable) ##"); ropChain.Add("## ESP: ???????? -> No Change ##"); ropChain.Add("## EBP: ???????? -> Jmp Esp # Call Esp ##"); ropChain.Add("## ESI: ???????? -> ApiAddresses[\"VirtualAlloc\"] ##"); ropChain.Add("## EDI: ???????? -> RopNop ##"); ropChain.Add("## ##"); ropChain.Add("## + place ptr to \"jmp esp\" on stack, below PUSHAD ##"); ropChain.Add("################################################################"); ropChain.Add(""); } foreach (Tuple k in rcg.VirtualAllocChain) { Array.Reverse(k.Item1, 0, k.Item1.Length); ropChain.Add(BitConverter.ToString(k.Item1).Replace("-", "\\x") + " | " + k.Item2); } ropChain.Add(Environment.NewLine); if (rcg.HeapCreateChain.Count > 0) { ropChain.Add("------------------------------------------------------------------------------------------------------------------------"); ropChain.Add("Method: HeapCreate Process Name: " + rcg.RcgInfo.ProcessName); ropChain.Add("------------------------------------------------------------------------------------------------------------------------"); ropChain.Add(""); ropChain.Add("################################################################"); ropChain.Add("## HeapCreate Template: ##"); ropChain.Add("## EAX: 90909090 -> Nop sled ##"); ropChain.Add("## ECX: 00010000 -> dwMaximumSize ##"); ropChain.Add("## EDX: 00001000 -> dwInitialSize ##"); ropChain.Add("## EBX: 00040000 -> flOptions ##"); ropChain.Add("## ESP: ???????? -> No Change ##"); ropChain.Add("## EBP: ???????? -> Jmp Esp # Call Esp ##"); ropChain.Add("## ESI: ???????? -> ApiAddresses[\"HeapCreate\"] ##"); ropChain.Add("## EDI: ???????? -> RopNop ##"); ropChain.Add("################################################################"); ropChain.Add(""); } foreach (Tuple k in rcg.HeapCreateChain) { Array.Reverse(k.Item1, 0, k.Item1.Length); ropChain.Add(BitConverter.ToString(k.Item1).Replace("-", "\\x") + " | " + k.Item2); } ropChain.Add(Environment.NewLine); if (rcg.VirtualProtectChain.Count > 0) { ropChain.Add("------------------------------------------------------------------------------------------------------------------------"); ropChain.Add("Method: VirtualProtect Process Name: " + rcg.RcgInfo.ProcessName); ropChain.Add("------------------------------------------------------------------------------------------------------------------------"); ropChain.Add(""); ropChain.Add("################################################################"); ropChain.Add("## VirtualProtect Template: ##"); ropChain.Add("## EAX: 90909090 -> Nop sled ##"); ropChain.Add("## ECX: ???????? -> flAllocationType ##"); ropChain.Add("## EDX: 00000040 -> flNewProtect ##"); ropChain.Add("## EBX: ???????? -> Int size (area to be set as executable) ##"); ropChain.Add("## ESP: ???????? -> No Change ##"); ropChain.Add("## EBP: ???????? -> Jmp Esp # Call Esp ##"); ropChain.Add("## ESI: ???????? -> ApiAddresses[\"VirtualProtect\"] ##"); ropChain.Add("## EDI: ???????? -> RopNop ##"); ropChain.Add("## ##"); ropChain.Add("## + place ptr to \"jmp esp\" on stack, below PUSHAD ##"); ropChain.Add("################################################################"); ropChain.Add(""); } foreach (Tuple k in rcg.VirtualProtectChain) { Array.Reverse(k.Item1, 0, k.Item1.Length); ropChain.Add(BitConverter.ToString(k.Item1).Replace("-", "\\x") + " | " + k.Item2); } ropChain.Add(Environment.NewLine); File.WriteAllLines(ropChainPath, ropChain); } return ropChain.ToArray(); } #endregion #region RopChainGadgets64 /// /// Produces output files containing information about the associated ROP chain, produces files containing ROP gadgets and the associated ROP chain. /// /// The ROP chain generator object /// Bool to indicate if ROP chains should be included or just gadget lists generated /// Returns an array of strings public static string[] RopChainGadgets64(RopChainGenerator64 rcg, bool gadgetsOnly = false) { string output = ""; List totalGadgets = new List(); List curatedGadgets = new List(); string totalGadgetsPath = GetFilePath(rcg.RcgInfo.WorkingDirectory, "total_gadgest_64_", ".txt"); string curatedGadgetsPath = GetFilePath(rcg.RcgInfo.WorkingDirectory, "curated_gadgest_64_", ".txt"); string ropChainPath = GetFilePath(rcg.RcgInfo.WorkingDirectory, "rop_chain_64_", ".txt"); output += "-------------------------------------------------------------------------------------------------------------------------" + Environment.NewLine; if (rcg.RcgInfo.Author != "No_Author_Set") { output += "Process Name: " + rcg.RcgInfo.ProcessName + " Gadget list created by: " + rcg.RcgInfo.Author + " " + Environment.NewLine; } else { output += "Process Name: " + rcg.RcgInfo.ProcessName + " ROP chain gadget list" + Environment.NewLine; } output += "-------------------------------------------------------------------------------------------------------------------------" + Environment.NewLine; totalGadgets.Add(output); curatedGadgets.Add(output); totalGadgets.Add("pushRax: "); curatedGadgets.Add("pushRax: "); foreach (KeyValuePair k in rcg.x64Opcodes.pushRax) { if (k.Value.Contains("push rax") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); } } } totalGadgets.Add("pushRbx: "); curatedGadgets.Add("pushRbx: "); foreach (KeyValuePair k in rcg.x64Opcodes.pushRbx) { if (k.Value.Contains("push rbx") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); } } } totalGadgets.Add("pushRcx: "); curatedGadgets.Add("pushRcx: "); foreach (KeyValuePair k in rcg.x64Opcodes.pushRcx) { if (k.Value.Contains("push rcx") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); } } } totalGadgets.Add("pushRdx: "); curatedGadgets.Add("pushRdx: "); foreach (KeyValuePair k in rcg.x64Opcodes.pushRdx) { if (k.Value.Contains("push rdx") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); } } } totalGadgets.Add("pushRsp: "); curatedGadgets.Add("pushRsp: "); foreach (KeyValuePair k in rcg.x64Opcodes.pushRsp) { if (k.Value.Contains("push rsp") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); } } } totalGadgets.Add("pushRbp: "); curatedGadgets.Add("pushRbp: "); foreach (KeyValuePair k in rcg.x64Opcodes.pushRbp) { if (k.Value.Contains("push rbp") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); } } } totalGadgets.Add("pushRsi: "); curatedGadgets.Add("pushRsi: "); foreach (KeyValuePair k in rcg.x64Opcodes.pushRsi) { if (k.Value.Contains("push rsi") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); } } } totalGadgets.Add("pushRdi: "); curatedGadgets.Add("pushRdi: "); foreach (KeyValuePair k in rcg.x64Opcodes.pushRdi) { if (k.Value.Contains("push rdi") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); } } } totalGadgets.Add("JmpRsp: "); curatedGadgets.Add("JmpRsp: "); foreach (KeyValuePair k in rcg.x64Opcodes.jmpRsp) { if (k.Value.Contains("jmp rsp")) { totalGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); } } } totalGadgets.Add("CallRsp: "); curatedGadgets.Add("CallRsp: "); foreach (KeyValuePair k in rcg.x64Opcodes.callRsp) { if (k.Value.Contains("call rsp")) { totalGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); } } } totalGadgets.Add("xorEax: "); curatedGadgets.Add("xorEax: "); foreach (KeyValuePair k in rcg.x64Opcodes.xorRax) { if (k.Value.Contains("xor eax") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); } } } totalGadgets.Add("xorRbx: "); curatedGadgets.Add("xorRbx: "); foreach (KeyValuePair k in rcg.x64Opcodes.xorRbx) { if (k.Value.Contains("xor rbx") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); } } } totalGadgets.Add("xorRcx: "); curatedGadgets.Add("xorRcx: "); foreach (KeyValuePair k in rcg.x64Opcodes.xorRcx) { if (k.Value.Contains("xor rcx") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); } } } totalGadgets.Add("xorRdx: "); curatedGadgets.Add("xorRdx: "); foreach (KeyValuePair k in rcg.x64Opcodes.xorRdx) { if (k.Value.Contains("xor rdx") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); } } } totalGadgets.Add("xorRsi: "); curatedGadgets.Add("xorRsi: "); foreach (KeyValuePair k in rcg.x64Opcodes.xorRsi) { if (k.Value.Contains("xor rsi") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); } } } totalGadgets.Add("xorRdi: "); curatedGadgets.Add("xorRdi: "); foreach (KeyValuePair k in rcg.x64Opcodes.xorRdi) { if (k.Value.Contains("xor rdi") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); } } } totalGadgets.Add("popRax: "); curatedGadgets.Add("popRax: "); foreach (KeyValuePair k in rcg.x64Opcodes.popRax) { if (k.Value.Contains("pop rax") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); } } } totalGadgets.Add("popRbx: "); curatedGadgets.Add("popRbx: "); foreach (KeyValuePair k in rcg.x64Opcodes.popRbx) { if (k.Value.Contains("pop rbx") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); } } } totalGadgets.Add("popRcx: "); curatedGadgets.Add("popRcx: "); foreach (KeyValuePair k in rcg.x64Opcodes.popRcx) { if (k.Value.Contains("pop rcx") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); } } } totalGadgets.Add("popRdx: "); curatedGadgets.Add("popRdx: "); foreach (KeyValuePair k in rcg.x64Opcodes.popRdx) { if (k.Value.Contains("pop rdx") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); } } } totalGadgets.Add("popRsp: "); curatedGadgets.Add("popRsp: "); foreach (KeyValuePair k in rcg.x64Opcodes.popRsp) { if (k.Value.Contains("pop rsp") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); } } } totalGadgets.Add("popRbp: "); curatedGadgets.Add("popRbp: "); foreach (KeyValuePair k in rcg.x64Opcodes.popRbp) { if (k.Value.Contains("pop rbp") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); } } } totalGadgets.Add("popRsi: "); curatedGadgets.Add("popRsi: "); foreach (KeyValuePair k in rcg.x64Opcodes.popRsi) { if (k.Value.Contains("pop rsi") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); } } } totalGadgets.Add("popRdi: "); curatedGadgets.Add("popRdi: "); foreach (KeyValuePair k in rcg.x64Opcodes.popRdi) { if (k.Value.Contains("pop rdi") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); } } } totalGadgets.Add("incRax: "); curatedGadgets.Add("incRax: "); foreach (KeyValuePair k in rcg.x64Opcodes.incRax) { if (k.Value.Contains("inc rax") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); } } } totalGadgets.Add("decRax: "); curatedGadgets.Add("decRax: "); foreach (KeyValuePair k in rcg.x64Opcodes.decRax) { if (k.Value.Contains("dec eax") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); } } } totalGadgets.Add("incRbx: "); curatedGadgets.Add("incRbx: "); foreach (KeyValuePair k in rcg.x64Opcodes.incRbx) { if (k.Value.Contains("inc rbx") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); } } } totalGadgets.Add("decRbx: "); curatedGadgets.Add("decRbx: "); foreach (KeyValuePair k in rcg.x64Opcodes.decRbx) { if (k.Value.Contains("dec ebx") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); } } } totalGadgets.Add("incRcx: "); curatedGadgets.Add("incRcx: "); foreach (KeyValuePair k in rcg.x64Opcodes.incRcx) { if (k.Value.Contains("inc rcx") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); } } } totalGadgets.Add("decRcx: "); curatedGadgets.Add("decRcx: "); foreach (KeyValuePair k in rcg.x64Opcodes.decRcx) { if (k.Value.Contains("dec ecx") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); } } } totalGadgets.Add("incRdx: "); curatedGadgets.Add("incRdx: "); foreach (KeyValuePair k in rcg.x64Opcodes.incRdx) { if (k.Value.Contains("inc rdx") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); } } } totalGadgets.Add("decRdx: "); curatedGadgets.Add("decRdx: "); foreach (KeyValuePair k in rcg.x64Opcodes.decRdx) { if (k.Value.Contains("dec edx") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); } } } totalGadgets.Add("incRbp: "); curatedGadgets.Add("incRbp: "); foreach (KeyValuePair k in rcg.x64Opcodes.incRbp) { if (k.Value.Contains("inc rbp") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); } } } totalGadgets.Add("decRbp: "); curatedGadgets.Add("decRbp: "); foreach (KeyValuePair k in rcg.x64Opcodes.decRbp) { if (k.Value.Contains("dec ebp") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); } } } totalGadgets.Add("incRsp: "); curatedGadgets.Add("incRsp: "); foreach (KeyValuePair k in rcg.x64Opcodes.incRsp) { if (k.Value.Contains("inc rsp") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); } } } totalGadgets.Add("decRsp: "); curatedGadgets.Add("decRsp: "); foreach (KeyValuePair k in rcg.x64Opcodes.decRsp) { if (k.Value.Contains("dec esp") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); } } } totalGadgets.Add("incRsi: "); curatedGadgets.Add("incRsi: "); foreach (KeyValuePair k in rcg.x64Opcodes.incRsi) { if (k.Value.Contains("inc rsi") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); } } } totalGadgets.Add("decRsi: "); curatedGadgets.Add("decRsi: "); foreach (KeyValuePair k in rcg.x64Opcodes.decRsi) { if (k.Value.Contains("dec esi") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); } } } totalGadgets.Add("incRdi: "); curatedGadgets.Add("incRdi: "); foreach (KeyValuePair k in rcg.x64Opcodes.incRdi) { if (k.Value.Contains("inc rdi") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); } } } totalGadgets.Add("decRdi: "); curatedGadgets.Add("decRdi: "); foreach (KeyValuePair k in rcg.x64Opcodes.decRdi) { if (k.Value.Contains("dec edi") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); } } } totalGadgets.Add("Add: "); curatedGadgets.Add("Add: "); foreach (KeyValuePair k in rcg.x64Opcodes.add) { if (k.Value.Contains("add") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); } } } totalGadgets.Add("Mov: "); curatedGadgets.Add("Mov: "); foreach (KeyValuePair k in rcg.x64Opcodes.mov) { if (k.Value.Contains("mov") && k.Value.Contains("ret")) { totalGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); if (!k.Value.Any(char.IsDigit) && !k.Value.ToLower().Contains("invalid")) { curatedGadgets.Add("0x" + k.Key.ToString("X16") + " | " + k.Value); } } } File.WriteAllLines(totalGadgetsPath, totalGadgets); File.WriteAllLines(curatedGadgetsPath, curatedGadgets); List ropChain = new List(); if (gadgetsOnly == false) { if (rcg.VirtualAllocChain.Count > 0) { ropChain.Add("------------------------------------------------------------------------------------------------------------------------"); ropChain.Add("Method: VirtualAlloc Process Name: " + rcg.RcgInfo.ProcessName); ropChain.Add("------------------------------------------------------------------------------------------------------------------------"); ropChain.Add(""); ropChain.Add("################################################################"); ropChain.Add("## VirtualAlloc Template: ##"); ropChain.Add("## RCX: 0x???????????????? -> Pointer (copys RSP) ##"); ropChain.Add("## RDX: 0x0000000000000500 -> dwSize ##"); ropChain.Add("## R8 : 0x0000000000001000 -> flAllocationType ##"); ropChain.Add("## R9 : 0x0000000000000040 -> flProtect ##"); ropChain.Add("## ##"); ropChain.Add("## + place a pointer to VirtualAlloc on stack ##"); ropChain.Add("## + place ptr to \"jmp rsp\" on stack ##"); ropChain.Add("################################################################"); ropChain.Add(""); } foreach (Tuple k in rcg.VirtualAllocChain) { Array.Reverse(k.Item1, 0, k.Item1.Length); ropChain.Add(BitConverter.ToString(k.Item1).Replace("-", "\\x") + " | " + k.Item2); } ropChain.Add(Environment.NewLine); if (rcg.HeapCreateChain.Count > 0) { ropChain.Add("------------------------------------------------------------------------------------------------------------------------"); ropChain.Add("Method: HeapCreate Process Name: " + rcg.RcgInfo.ProcessName); ropChain.Add("------------------------------------------------------------------------------------------------------------------------"); ropChain.Add(""); ropChain.Add("################################################################"); ropChain.Add("## HeapCreate Template: ##"); ropChain.Add("## RCX: 0x0000000000040000 -> flOptions ##"); ropChain.Add("## RDX: 0x0000000000000500 -> dwInitialSize ##"); ropChain.Add("## R8 : 0x0000000000001000 -> dwMaximumSize ##"); ropChain.Add("## ##"); ropChain.Add("## + place a pointer to VirtualAlloc on stack ##"); ropChain.Add("## + place ptr to \"jmp rax\" on stack ##"); ropChain.Add("################################################################"); ropChain.Add(""); } foreach (Tuple k in rcg.HeapCreateChain) { Array.Reverse(k.Item1, 0, k.Item1.Length); ropChain.Add(BitConverter.ToString(k.Item1).Replace("-", "\\x") + " | " + k.Item2); } ropChain.Add(Environment.NewLine); if (rcg.VirtualProtectChain.Count > 0) { ropChain.Add("------------------------------------------------------------------------------------------------------------------------"); ropChain.Add("Method: VirtualProtect Process Name: " + rcg.RcgInfo.ProcessName); ropChain.Add("------------------------------------------------------------------------------------------------------------------------"); ropChain.Add(""); ropChain.Add("################################################################"); ropChain.Add("## VirtualProtect Template: ##"); ropChain.Add("## RCX: 0x???????????????? -> Pointer (copys RSP) ##"); ropChain.Add("## RDX: 0x0000000000000500 -> dwSize ##"); ropChain.Add("## R8 : 0x0000000000001000 -> flAllocationType ##"); ropChain.Add("## R9 : 0x???????????????? -> flProtect (copys RSP) ##"); ropChain.Add("## ##"); ropChain.Add("## + place a pointer to VirtualAlloc on stack ##"); ropChain.Add("## + place ptr to \"jmp rsp\" on stack ##"); ropChain.Add("################################################################"); ropChain.Add(""); } foreach (Tuple k in rcg.VirtualProtectChain) { Array.Reverse(k.Item1, 0, k.Item1.Length); ropChain.Add(BitConverter.ToString(k.Item1).Replace("-", "\\x") + " | " + k.Item2); } ropChain.Add(Environment.NewLine); File.WriteAllLines(ropChainPath, ropChain); } return ropChain.ToArray(); } private static string ConvertRopElementToString(Tuple element) { string ret = "0x" + element.Item1.ToString("X16") + " | " + element.Item2; return ret; } #endregion #region Assemble Opcodes /// /// Converts a collection of instructions into the associated opcodes. /// /// An array containing either x86 or x64 instructions. /// Uint representing the machine type (x86 = 0, x64 = 1) /// Returns null if the method fails. public static string[] AssembleOpcodes(string[] instructions, uint machine) { string[] opcodeArray = null; MachineType mt; if(machine == 0) { mt = MachineType.I386; } else if(machine == 1) { mt = MachineType.x64; } else { throw new ERCException("Invalid machine type provided. Value provided = " + machine + ". Uint 0 = x86, 1 = x64"); } var instructionsList = instructions.ToList(); var asmResult = OpcodeAssembler.AssembleOpcodes(instructionsList, mt); if (asmResult.Error != null) { throw asmResult.Error; } string opcodes = BitConverter.ToString(asmResult.ReturnValue).Replace("-", " "); opcodeArray = opcodes.Split(' '); return opcodeArray; } /// /// Converts a collection of instructions into the associated opcodes. /// /// An array containing either x86 or x64 instructions. /// MachineType of the instruction set to be assembled. /// Returns null if the method fails. public static string[] AssembleOpcodes(string[] instructions, MachineType machine) { string[] opcodeArray = null; if(machine != MachineType.I386 && machine != MachineType.x64) { throw new ERCException("Invalid machine type provided."); } var instructionsList = instructions.ToList(); var asmResult = OpcodeAssembler.AssembleOpcodes(instructionsList, machine); if(asmResult.Error != null) { throw asmResult.Error; } string opcodes = BitConverter.ToString(asmResult.ReturnValue).Replace("-", " "); opcodeArray = opcodes.Split(' '); return opcodeArray; } #endregion #region Disassemble Opcodes /// /// Converts a collection of opcodes into the associated instructions. /// /// An array containing either x86 or x64 opcodes. /// Uint representing the machine type (x86 = 0, x64 = 1) /// Returns null if the method fails. public static string[] DisassembleOpcodes(byte[] opcodes, uint machine) { string[] instructionArray = null; MachineType mt; if (machine == 0) { mt = MachineType.I386; } else if (machine == 1) { mt = MachineType.x64; } else { throw new ERCException("Invalid machine type provided. Value provided = " + machine + ". Uint 0 = x86, 1 = x64"); } var disassembledInstructions = OpcodeDisassembler.Disassemble(opcodes, mt); if (disassembledInstructions.Error != null) { throw disassembledInstructions.Error; } instructionArray = disassembledInstructions.ReturnValue.Split('\n'); return instructionArray; } /// /// Converts a collection of opcodes into the associated instructions. /// /// An array containing either x86 or x64 opcodes. /// MachineType of the instruction set to be assembled. /// Returns null if the method fails. public static string[] DisassembleOpcodes(byte[] opcodes, MachineType machine) { string[] instructionArray = null; if (machine != MachineType.I386 && machine != MachineType.x64) { throw new ERCException("Invalid machine type provided."); } var disassembledInstructions = OpcodeDisassembler.Disassemble(opcodes, machine); if(disassembledInstructions.Error != null) { throw disassembledInstructions.Error; } instructionArray = disassembledInstructions.ReturnValue.Split('\n'); return instructionArray; } #endregion #region StringToByteArray /// /// Converts a string of hex characters to a byte array of the associated values. /// /// A string containing hex characters. /// Returns a byte array. private static byte[] StringToByteArray(string hex) { return Enumerable.Range(0, hex.Length) .Where(x => x % 2 == 0) .Select(x => System.Convert.ToByte(hex.Substring(x, 2), 16)) .ToArray(); } #endregion #region Dump Memory /// /// Reads a set of bytes from process memory and provides a string contianing the results. /// /// ProcessInfo object /// The address to start reading from. /// The number of bytes to read. /// Bool indicating if output should be written to a file. /// A string containing the bytes read from memory public static string DumpMemory(ProcessInfo info, IntPtr startAddress, int length, bool writeToFile = true) { string dumpFilename = GetFilePath(info.WorkingDirectory, "MemoryDump_", ".txt"); ErcResult result = info.DumpMemoryRegion(startAddress, length); string output = ""; int bytesPerLine = 0; Console.WriteLine("Here 1"); if (info.ProcessMachineType == MachineType.I386) { bytesPerLine = 8; } else { bytesPerLine = 16; } output += "----------------------------------------------------------------------------------------------------------------------" + Environment.NewLine; output += "Contents of memory region 0x" + startAddress.ToString("X" + bytesPerLine) + " - 0x" + (startAddress + length).ToString("X" + bytesPerLine) + " Created at: " + DateTime.Now + ". Created by: " + info.Author + Environment.NewLine; output+= "----------------------------------------------------------------------------------------------------------------------" + Environment.NewLine; for (int i = 0; i < result.ReturnValue.Length; i++) { if (i == 0) { output += startAddress.ToString("X" + bytesPerLine) + ": " + result.ReturnValue[i].ToString("X2") + " "; } else if (i % bytesPerLine == 0) { output += Environment.NewLine; output += (startAddress + ((i / bytesPerLine) * bytesPerLine)).ToString("X" + bytesPerLine) + ": " + result.ReturnValue[i].ToString("X2") + " "; } else { output += result.ReturnValue[i].ToString("X2") + " "; } } if (writeToFile == true) { File.WriteAllText(dumpFilename, output); } Console.WriteLine("Here 3"); return output; } #endregion #region Dump Heap /// /// Reads a set of bytes from a specific heap and provides a string contianing the results. Either HeapID or startAddress must be supplied. If both are supplied HeapID takes precedence. /// /// HeapInfo object /// The ID of the heap to be dumped. (optional) /// The start address of the specific heap block to be dumped in hexadecimal. (optional) /// Bool indicating if output should be written to a file.(optional) /// A string containing the bytes read from memory public static string[] DumpHeap(HeapInfo hi, ulong heapid = 0, string hexStartAddress = "", bool writeToFile = true) { List output = new List(); if (hexStartAddress.Contains("0x") || hexStartAddress.Contains("0x") || hexStartAddress.Contains("x") || hexStartAddress.Contains("X")) { hexStartAddress = hexStartAddress.Replace("0x", ""); hexStartAddress = hexStartAddress.Replace("0X", ""); hexStartAddress = hexStartAddress.Replace("X", ""); hexStartAddress = hexStartAddress.Replace("x", ""); } ulong startAddress = 0; if (hi.HeapProcess.ProcessMachineType == MachineType.I386) { try { startAddress = (uint)System.Convert.ToInt32(hexStartAddress, 16); } catch { } } else { try { startAddress = (ulong)System.Convert.ToInt64(hexStartAddress, 16); } catch { } } if (heapid == 0 && startAddress == 0) { List ret = new List(); ret.Add("Neither heapID or start address supplied. One must be supplied in order to utilize this method."); return ret.ToArray(); } Dictionary searches = new Dictionary(); if(heapid != 0) { foreach (Structures.HEAPENTRY32 he in hi.HeapEntries) { if ((ulong)he.th32HeapID == heapid) { if (!searches.ContainsKey(he.dwAddress)) { searches.Add(he.dwAddress, (int)he.dwBlockSize); } } } } else { foreach (Structures.HEAPENTRY32 he in hi.HeapEntries) { if ((ulong)he.dwAddress == startAddress) { heapid = (ulong)he.th32HeapID; if (!searches.ContainsKey(he.dwAddress)) { searches.Add(he.dwAddress, (int)he.dwBlockSize); } } } } string dumpFilename = GetFilePath(hi.HeapProcess.WorkingDirectory, "HeapDump_", ".txt"); int bytesPerLine = 0; output.Add("----------------------------------------------------------------------------------------------------------------------" + Environment.NewLine); output.Add("Contents of process heap: " + heapid + " Created at: " + DateTime.Now + ". Created by: " + hi.HeapProcess.Author + Environment.NewLine); output.Add("----------------------------------------------------------------------------------------------------------------------" + Environment.NewLine); if (hi.HeapProcess.ProcessMachineType == MachineType.I386) { bytesPerLine = 8; } else { bytesPerLine = 16; } foreach (KeyValuePair kv in searches) { ErcResult result = hi.HeapProcess.DumpMemoryRegion(kv.Key, kv.Value); for (int i = 0; i < result.ReturnValue.Length; i++) { if (i == 0) { output.Add(Environment.NewLine + kv.Key.ToString("X" + bytesPerLine) + ": " + result.ReturnValue[i].ToString("X2") + " "); } else if (i % bytesPerLine == 0) { output.Add(Environment.NewLine); output.Add((kv.Key + ((i / bytesPerLine) * bytesPerLine)).ToString("X" + bytesPerLine) + ": " + result.ReturnValue[i].ToString("X2") + " "); } else { output.Add(result.ReturnValue[i].ToString("X2") + " "); } } } if (writeToFile == true) { File.WriteAllLines(dumpFilename, output); } return output.ToArray(); } #endregion #region Heap Stats /// /// Returns statistics about the heap information gathered about the current process. /// /// /// Returns an of strings public static string[] HeapStats(HeapInfo hi, ulong heapID = 0, string hexStartAddress = "", bool extended = false) { List result = new List(); result = new List(); result.Add("----------------------------------------------------------------------------------------------------------------------" + Environment.NewLine); result.Add("Heap statistics for process: " + hi.HeapProcess.ProcessName + " Created at: " + DateTime.Now + ". Created by: " + hi.HeapProcess.Author + Environment.NewLine); result.Add("----------------------------------------------------------------------------------------------------------------------" + Environment.NewLine); foreach (string s in hi.HeapStatistics(extended, heapID, hexStartAddress).ReturnValue) { result.Add(s); } return result.ToArray(); } #endregion #region ListHeapIDs /// /// Returns a list of IDs for each heap associated with the current process. /// /// A HeapInfo object. /// Retruns an array of strings containing the heapIds. public static string[] ListHeapIDs(HeapInfo hi) { var output = hi.HeapIDs(); List result = new List(); result.Add("----------------------------------------------------------------------------------------------------------------------" + Environment.NewLine); result.Add("Heap IDs associated with process: " + hi.HeapProcess.ProcessName + " Created at: " + DateTime.Now + ". Created by: " + hi.HeapProcess.Author + Environment.NewLine); result.Add("----------------------------------------------------------------------------------------------------------------------" + Environment.NewLine); int heapnum = 1; foreach(ulong ul in output.ReturnValue) { result.Add("Heap " + heapnum + " ID = " + ul + Environment.NewLine); } return result.ToArray(); } #endregion #region Search Heap /// /// Searches the process heap for a specific byte patters. If heapID and hexStartAddress are specified heapID takes precedence. Takes an optional bool indicating if output should be written to file. /// /// HeapInfo object. /// Pattern to be searched for. /// Optional parameter indicating which heap to search. /// Optional parameter indicating the start address of the heap object to search /// Bool indicating if the output should be written to file. /// Returns an array of strings. public static string[] SearchHeap(HeapInfo hi, byte[] searchBytes, ulong heapID = 0, string hexStartAddress = "", bool writeToFile = true) { var output = hi.SearchHeap(searchBytes, heapID, hexStartAddress); List result = new List(); if(output.Error != null) { result.Add("ERROR: " + output.Error.Message + Environment.NewLine); } if(output.ReturnValue.Count == 0) { result.Add(String.Format("Search table on {0} by {1}. Search string: 0x{2}", DateTime.Now, hi.HeapProcess.Author, BitConverter.ToString(searchBytes).Replace("-", "")) + Environment.NewLine); result.Add("----------------------------------------------------------------------" + Environment.NewLine); result.Add("No instances of the pattern were found." + Environment.NewLine); return result.ToArray(); } result.Add(String.Format("Search table created on {0} by {1}. Search string: 0x{2}", DateTime.Now, hi.HeapProcess.Author, BitConverter.ToString(searchBytes).Replace("-", "")) + Environment.NewLine); result.Add("----------------------------------------------------------------------" + Environment.NewLine); if(hi.HeapProcess.ProcessMachineType == MachineType.I386) { result.Add(" Address | Heap ID | Heap Entry Start Address " + Environment.NewLine); foreach (Tuple t in output.ReturnValue) { result.Add(" 0x" + t.Item1.ToString("X8") + " | " + (uint)t.Item2 + " | 0x" + t.Item3.ToString("X8") + Environment.NewLine); } } else { result.Add(" Address | Heap ID | Heap Entry Start Address " + Environment.NewLine); foreach (Tuple t in output.ReturnValue) { result.Add(" 0x" + t.Item1.ToString("X16") + " | " + (ulong)t.Item2 + " | 0x" + t.Item3.ToString("X16") + Environment.NewLine); } } result.Add(Environment.NewLine); return result.ToArray(); } #endregion } } ================================================ FILE: ERC/ERC/ERC.Net.csproj ================================================  net472 AnyCPU;x64;x86 true x86 ..\..\ERC.net\ERC\ERC.Net.xml true x86 ..\..\ERC.net\ERC\ERC.Net.xml true x64 ..\..\ERC.net\ERC\ERC.Net.xml true x64 true x86 true x64 all runtime; build; native; contentfiles; analyzers; buildtransitive ..\..\ConsoleApp1\ConsoleApp1\bin\Debug\Fasm.NET.dll ..\..\ConsoleApp1\ConsoleApp1\bin\Debug\Reloaded.Assembler.dll ..\..\ConsoleApp1\ConsoleApp1\bin\Debug\Reloaded.Memory.dll ..\..\ConsoleApp1\ConsoleApp1\bin\Debug\Reloaded.Memory.Buffers.dll ================================================ FILE: ERC/ERC/ERC.Net.xml ================================================ ERC.Net Static class containing methods for common conversions. Converts a hex string to ASCII." A string containing hex characters. A string containing the equivalent ASCII values Converts a hex string to the equivalent bytes. A string containing hex characters. A byte array containing the associated values. Converts an ASCII string to a byte array. An ASCII string. A byte array containing the associated values. Converts an ASCII string to a hex string An ASCII string. A hex string. Converts a Unicode string to a byte array. A Unicode string. A byte array. Converts a Unicode string to a hex string. A Unicode string. A hex string. Converts a UTF-7 string to a byte array. A UTF-7 string. A byte array. Converts a UTF-7 string to a hex string. A UTF-7 string. A hex string. Converts a UTF-8 string to a byte array. A UTF-8 string. A byte array. Converts a UTF-8 string to a hex string. A UTF-8 string. A hex string. Converts a UTF-32 string to a byte array. A UTF-32 string. A byte array. Converts a UTF-32 string to a hex string. A UTF-32 string. A hex string. OpcodeAssembler class, can be declared and inherit from a ProcessInfo object to inherit the values of the current process or be called as a static function to assemble instructions. Constructor. ProcessInfo object to be inherited from. Takes either an array or list of strings containing assembly instructions and returns the associated opcodes. The instructions to be assembled Returns an ErcResult byte array containing the assembled instructions Takes either an array or list of strings containing assembly instructions, a MachineType of I386 or x64, an instance of the ERC_Core object and returns the associated opcodes. The instructions to be assemble=d a ERC.MachineType of either I386 or x64 Returns an ERC_Result byte array containing the assembled instructions OpcodeDisassembler class, can be declared and inherit from a ProcessInfo object to inherit the values of the current process or be called as a static function to disassemble opcodes. Constructor. ProcessInfo object to be inherited from. Disassembles opcodes into the associated instructions. Takes a byte array containing opcodes. The opcodes to be disassembled Returns an ERC_Result containing associated instructions. Disassembles opcodes into the associated instructions. Takes a byte array containing opcodes, a MachineType of I386 or x64, an instance of the ERC_Core object and returns an ERC_Result containing associated instructions. A byte array containing opcodes to be disassembled a ERC.MachineType of either I386 or x64 Returns an ERC_Result containing associated instructions. Static class used to build a non repeating pattern and identify the position of a string in a non repeating pattern. Creates a string of non repeating characters. The length of the pattern to be created as integer An ErcCore object (Optional) bool specifying whether the extended character set should be used Returns an ErcResult string containing the generated pattern Takes a string of characters and returns the location of the first character in a pattern created by Pattern_Create. The pattern to be searched for. An ErcCore object (Optional) bool specifying whether the extended character set should be used Returns an ErcResult int containing the offset of the supplied pattern within the generated pattern A collecton of methods which generate payloads. Default egg hunter tag. A 64 bit egg hunter. A second 64 bit egg hunter. A 32 bit egg hunter. An egg hunter that will work on 32 bit systems or 32 bit processes running under WOW64. Creates an array of all possible byte values except those passed to the function. Takes a byte array of bytes to be excluded Returns an array of all other possible bytes. Generates a selection of EggHunter payloads. A custom tag can be specified, if no tag is specified EggHunters will search for the default tag (ERCD) A custom tag which the egg hunters will search for. Returns a dictionary containing a list of EggHunters and string detailing them Finds all instances of POP X POP X RET in a given byte array. Byte array to be searched Returns an array of integers containing the offsets of the instruction sets. Compares a byte array with an area in memory of equal size. This method should be used in conjunction with the ByteArrayConstructor to identify bytes which can not be passed into a program without corrupting the input. The process to compare memory from The address at which to start the comparison The byte array containing the bytes to be compared Returns a Tuple containing a bool which is true if the comparison was identical and false if it was not, a byte array containing the bytes provided and a byte array containing the bytes read from process memory Compares a byte array with an area in memory of equal size. This method should be used in conjunction with the ByteArrayConstructor to identify bytes which can not be passed into a program without corrupting the input. The process to compare memory from The address at which to start the comparison The path to a file containing the bytes to be compared Returns a Tuple containing a bool which is true if the comparison was identical and false if it was not, a byte array containing the bytes provided and a byte array containing the bytes read from process memory Contains methods for identifying and removing pointers to unwanted data. Removes pointers which contain unwanted bytes. MachineType architecture of the associated process. The list from which to remove the pointers If a pointer contains any of these bytes it will be discarded Returns a ErcResult of List IntPtr Removes pointers which contain unwanted bytes. MachineType architecture of the associated process. The list from which to remove the pointers If a pointer contains any of these bytes it will be discarded Returns a ErcResult of Dictionary IntPtr, String Removes pointers from a dictionary when pointers do not have the protection level specified. ProcessInfo object of the associated process. List of pointers. Specified protection level of pointers. Returns a Dictionary of Intptr, string Removes pointers from a dictionary when pointers do not have the protection level specified. ProcessInfo object of the associated process. List of pointers. Specified protection level of pointers. Returns a Dictionary of Intptr, string Attempts to create Rop chains from 64 bit processes. Contains a ROP chain which calls the VirtualAlloc method. Constructor. The ProcessInfo object. Creates a RopChain for a specific process. Takes a byte array of values used to disqualify ROP gadgets A Address to be used as the start location for which memory will be made executable A list of modules to be excluded from the search for ROP gadgets Returns an ErcResult string containing Creates a RopChain for a specific process. A Address to be used as the start location for which memory will be made executable A list of modules to be excluded from the search for ROP gadgets Returns an ErcResult string containing Gets the handles of 4 functions associated with building ROP chains: VirtualAlloc, HeapCreate, VirtualProtect and WriteProcessMemory Gets a list of RopNops from the current process memory. A list of modules to be excluded from the search Returns a ErcResult containing a list of IntPtr Checks for a combination of instructions that can be used to zero out a register, this can be a xor instruction on itself or a xor instruction elsewhere followed by a move to the selected register. This function should be extended with further methods for zeroing a register at a later date. The Register32 value for the register to be zeroed. The RegisterModifiers32 object. A dictionary(byte[], string) containing pointers to the instructions and the associated mnemonics Sets the flag of a Register32 enum in a RegisterModifiers32 class. This flag is used to identify whether setting the value of one register involved editing another register. For example if setting EAX involved modifying EBX then RegisterModifiers32.EAX will have the EBX flag set. Any register should not be able to modify the value of any other register twice. The purpose of this is to stop an infitinte loop where each register modifies the other in order to achieve the correct value. The Registers32 which is being modified The Registers32 which is doing the modification The RegisterModifiers32 object. Returns a boolean indicating whether one register has modified the value of another register attempting to set the correct value. The Registers32 which is being modified The Registers32 which is doing the modification The RegisterModifiers32 object. A bool, true = register was modified by this register false = register was not modified by this register Finds a mov instruction going from the src register to the destination register The destination register The source register Returns a tuple of byte[], string, Register32 containing a pointer to the instruction and the associated mnemonics Finds a add instruction going from the src register to the destination register The destination register The source register Returns a tuple of byte[], string, Register32 containing a pointer to the instruction and the associated mnemonics Checks all values of a Registers32 enum and returns false if any of them are not set. The Registers32 object to be tested A boolean value is returned Contains lists of instructions for specific registers. pushEax list. pushEbx list. pushEcx list. pushEdx list. pushEsp list. pushEbp list. pushEsi list. pushEdi list. jmpEsp list. callEsp list. xorEax list. xorEbx list. xorEcx list. xorEdx list. xorEsi list. xorEdi list. popEax list. popEbx list. popEcx list. popEdx list. popEsp list. popEbp list. popEsi list. popEdi list. pushad list. incEax list. incEbx list. incEcx list. incEdx list. incEbp list. incEsp list. incEsi list. incEdi list. decEax list. decEbx list. decEcx list. decEdx list. decEbp list. decEsp list. decEsi list. decEdi list. add list. sub list. mov list. and list. Attempts to create Rop chains from 64 bit processes. Contains a ROP chain which calls the VirtualAlloc method. Constructor ProcessInfo object for which a ROP chain will be generated Creates a RopChain for a specific process. Takes a byte array of values used to disqualify ROP gadgets A Address to be used as the start location for which memory will be made executable A list of modules to be excluded from the search for ROP gadgets Returns an ErcResult string containing Creates a RopChain for a specific process. A Address to be used as the start location for which memory will be made executable A list of modules to be excluded from the search for ROP gadgets Returns an ErcResult string containing Checks for a combination of instructions that can be used to zero out a register, this can be a xor instruction on itself or a xor instruction elsewhere followed by a move to the selected register. This function should be extended with further methods for zeroing a register at a later date. The Register64 value for the register to be zeroed. The RegisterModifiers64 object. A dictionary(byte[], string) containing pointers to the instructions and the associated mnemonics Sets the flag of a Register64 enum in a RegisterModifiers64 class. This flag is used to identify whether setting the value of one register involved editing another register. For example if setting EAX involved modifying RBX then RegisterModifiers32.RAX will have the RBX flag set. Any register should not be able to modify the value of any other register twice. The purpose of this is to stop an infitinte loop where each register modifies the other in order to achieve the correct value. The Register64 which is being modified The Register64 which is doing the modification The RegisterModifiers64 object. Finds a add instruction going from the src register to the destination register The destination register The source register Returns a tuple of byte[], string, Register64 containing a pointer to the instruction and the associated mnemonics Finds a sub instruction going from the src register to the destination register The destination register The source register Returns a tuple of byte[], string, Register64 containing a pointer to the instruction and the associated mnemonics Finds a mov instruction going from the src register to the destination register The destination register The source register The RegisterModifiers64 object. Returns a dictionary of byte[] string containing a pointer to the instruction and the associated mnemonics Contains lists of instructions for specific registers. pushRax list. pushRcx list. pushRdx list. pushRbx list. pushRsp list. pushRbp list. pushRsi list. pushRdi list. pushR8 list. pushR9 list. pushR10 list. pushR11 list. pushR12 list. pushR13 list. pushR14 list. pushR15 list. popRax list. popRbx list. popRcx list. popRdx list. popRsp list. popRbp list. popRsi list. popRdi list. popR8 list. popR9 list. popR10 list. popR11 list. popR12 list. popR13 list. popR14 list. popR15 list. xorRax list. xorRbx list. xorRcx list. xorRdx list. xorRsi list. xorRdi list. xorRsp list. xorRbp list. xorR8 list. xorR9 list. xorR10 list. xorR11 list. xorR12 list. xorR13 list. xorR14 list. xorR15 list. jmpRsp list. callRsp list. incRax list. incRbx list. incRcx list. incRdx list. incRbp list. incRsp list. incRsi list. incRdi list. incR8 list. incR9 list. incR10 list. incR11 list. incR12 list. incR13 list. incR14 list. incR15 list. decRax list. decRbx list. decRcx list. decRdx list. decRbp list. decRsp list. decRsi list. decRdi list. decR8 list. decR9 list. decR10 list. decR11 list. decR12 list. decR13 list. decR14 list. decR15 list. add list. mov list. sub list. Provides output in various human readable formats of data from the library. Identifies output files previously created by a the Display_Modules function and identifies the last number used. Returns the next number to be used as a filename. The directory to be used A prefix for the file name e.g. "modules_" or "Pattern_" etc The file extension to be used e.g. ".txt" Returns a string containing the full file path to be used when writing output to disk Writes a list of strings to a file. Takes a directory, filename and prefix along with a List of strings. The directory to be used A prefix for the file name e.g. "modules_" or "Pattern_" etc The file extension to be used e.g. ".txt" A list of strings to be written to disk Creates a file in the ErcCore working directory containing a string of non repeating characters. The length of the string to be created An ErcCore object A optional boolean specifying whether to use the extended character set. Default is false. Returns a string containing the pattern generated. Private function, should not be called directly. Takes input from pattern_create and outputs in an easily readable format. The pattern to be used An ErcCore object Returns a string containing the human readable output of the pattern create method. Lists usable processes running on the local machine. A string containing details of processes running on the local machine. Lists usable processes running on the remote machine. A string containing details of processes running on the remote machine. Displays information related to the provided ProcessInfo object. The ProcessInfo object of which the module information will be displayed Set to false to surpress file output. Displays information about all threads related to a specific process. Displays a list of all modules and associated information from a specific process. Can output to stdout, a file or both. The ProcessInfo object of which the module information will be displayed Returns a string containing all module info from a specific process Aquires filename and writes out all module data to the current working directory. Requires a Process_Info object to be passed as a parameter. The ProcessInfo object of which the module information will be displayed Set to false to surpress file output. Returns a formatted string of all results Searches the memory of a process and it's loaded modules for a string or byte combination. The processInfo object for the process The type of data to be searched for. The string to search for. Remove ASLR libraries. Remove SafeSEH libraries. Remove rebasable libraries. Remove NXCompat libraries. Remove OS Dlls. Addresses containing values in this byte array will be ignored. String containing protection level returned pointers will. Searches the loaded modules of a process for a string or byte combination. The processInfo object for the process The type of data to be searched for. The string to search for. Remove ASLR libraries. Remove SafeSEH libraries. Remove rebasable libraries. Remove NXCompat libraries. Remove OS Dlls. Addresses containing values in this byte array will be ignored. List of modules to be searched String containing protection level returned pointers will. Searches all memory associated with a given process and associated modules for POP X POP X RET instructions. Passing a list of module paths or names will exclude those modules from the search. Similar to Search_All_Memory_PPR however provides output in an easily readable format. The ProcessInfo object which will be searched for POP POP RET instructions. Remove ASLR libraries. Remove SafeSEH libraries. Remove rebasable libraries. Remove NXCompat libraries. Remove OS Dlls. Addresses containing values in this byte array will be ignored. String containing protection level returned pointers will. Returns an ErcResult containing a list of strings detailing the pointers, opcodes and base files of suitable instruction sets. Searches all memory associated with a given process and associated modules for POP X POP X RET instructions. Passing a list of module paths or names will exclude those modules from the search. Similar to Search_All_Memory_PPR however provides output in an easily readable format. The ProcessInfo object which will be searched for POP POP RET instructions Ptrs containing these byte values will be discarded. Modules to be ignored when searching for the instruction sets. Returns an ErcResult containing a list of strings detailing the pointers, opcodes and base files of suitable instruction sets. Searches all memory associated with a given process and associated modules for POP X POP X RET instructions. Passing a list of module paths or names will exclude those modules from the search. Similar to Search_All_Memory_PPR however provides output in an easily readable format. This version only returns unicode compliant pointers. The ProcessInfo object which will be searched for POP POP RET instructions. Remove ASLR libraries. Remove SafeSEH libraries. Remove rebasable libraries. Remove NXCompat libraries. Remove OS Dlls. Addresses containing values in this byte array will be ignored. String containing protection level returned pointers will. Returns an ErcResult containing a list of strings detailing the pointers, opcodes and base files of suitable instruction sets. Generates an array of all possible bytes for use when identifying bad characters. Writes the output to disk in the working directory. An array of bytes to be excluded from the final byte array An ErcCore object Returns a byte array of all possible bytes. Compares a the values contained in a memory region to the values in the supplied byte array. The processInfo object that contains the memory region. The memory address to start the search at. The byte array the region will be compared against. Returns a string detailing differences between the two. Generates a collection of EggHunter payloads. (Optional) If an ErcCore object is provided the output will also be written out to the working directory (Optional) If a tag is provided the payloads will be altered to search for that tag, the default tag is ERCD Returns a string containing all EggHunters Searches the memory of a process for a non repeating pattern. The ProcessInfo object of the process to be searched Integer specifiying the format of the string: 0 = search term is in bytes\n1 = search term is in unicode\n2 = search term is in ASCII\n3 = Search term is in UTF8\n4 = Search term is in UTF7\n5 = Search term is in UTF32 Whether the extended character range is to be used when searching for the non repeating pattern Returns a List of strings containing the locations the repeating pattern was identified Produces output files containing information about the associated ROP chain, produces files containing ROP gadgets and the associated ROP chain. The ROP chain generator object Returns a List of strings Produces output files containing information about the associated ROP chain, produces files containing ROP gadgets and the associated ROP chain. The ROP chain generator object Returns a List of strings Converts a collection of instructions into the associated opcodes. An array containing either x86 or x64 instructions. Uint representing the machine type (x86 = 0, x64 = 1) Returns null if the method fails. Converts a collection of instructions into the associated opcodes. An array containing either x86 or x64 instructions. MachineType of the instruction set to be assembled. Returns null if the method fails. Converts a collection of opcodes into the associated instructions. An array containing either x86 or x64 opcodes. Uint representing the machine type (x86 = 0, x64 = 1) Returns null if the method fails. Converts a collection of opcodes into the associated instructions. An array containing either x86 or x64 opcodes. MachineType of the instruction set to be assembled. Returns null if the method fails. Converts a string of hex characters to a byte array of the associated values. A string containing hex characters. Returns a byte array. Reads a set of bytes from process memory and provides a string contianing the results. ProcessInfo object The address to start reading from. The number of bytes to read. A string containing the bytes read from memroy Custom exception handler. Constructor for the ERCException class. The message associated with the Exception Creates a serializable exception. Stores all the data needed to serialize or deserialize an object. Describes the source and destination of a given serialized stream, and provides an additional caller-defined context. A single instance of this object should be instantiated at a minimum. It is used for storing global variables such as the working directory etc. The current version of the ERC.Net library The directory where output files will be saved. The Author to be credited in output files. Path of the current ERC_Config.xml file. Path where error details should be logged. Path to the file containing the standard pattern to be used. Path to the file containing the extended pattern to be used. Opens an existing local process object. The access to the process object. This access right is checked against the security descriptor for the process. If this value is TRUE, processes created by this process will inherit the handle. Otherwise, the processes do not inherit this handle. The identifier of the local process to be opened. If the function succeeds, the return value is an open handle to the specified process. Reads data from an area of memory in a specified process. The entire area to be read must be accessible or the operation fails. A handle to the process with memory that is being read. A pointer to the base address in the specified process from which to read. A pointer to a buffer that receives the contents from the address space of the specified process. The number of bytes to be read from the specified process. A pointer to a variable that receives the number of bytes transferred into the specified buffer. If the function succeeds, the return value is nonzero. Retrieves information about a range of pages within the virtual address space of a specified 32 bit process. A handle to the process whose memory information is queried. A pointer to the base address of the region of pages to be queried. A pointer to a MEMORY_BASIC_INFORMATION32 structure in which information about the specified page range is returned. The size of the buffer pointed to by the lpBuffer parameter, in bytes. The return value is the actual number of bytes returned in the information buffer. Retrieves information about a range of pages within the virtual address space of a specified 64 bit process. A handle to the process whose memory information is queried. A pointer to the base address of the region of pages to be queried. A pointer to a MEMORY_BASIC_INFORMATION64 structure in which information about the specified page range is returned. The size of the buffer pointed to by the lpBuffer parameter, in bytes. The return value is the actual number of bytes returned in the information buffer. Determines whether the specified process is running under WOW64 or an Intel64 of x64 processor. A handle to the process. A pointer to a value that is set to TRUE if the process is running under WOW64 on an Intel64 or x64 processor. If the function succeeds, the return value is a nonzero value. Opens an existing thread object. The access to the thread object. If this value is TRUE, processes created by this process will inherit the handle. The identifier of the thread to be opened. If the function succeeds, the return value is an open handle to the specified thread. Retrieves the context of the specified 32 bit thread. A handle to the thread whose context is to be retrieved. A pointer to a CONTEXT structure that receives the appropriate context of the specified thread. If the function succeeds, the return value is nonzero. Retrieves the context of the specified WOW64 thread. A handle to the thread whose context is to be retrieved. A pointer to a CONTEXT structure that receives the appropriate context of the specified thread. If the function succeeds, the return value is nonzero. Retrieves the context of the specified 64 bit thread. A handle to the thread whose context is to be retrieved. A pointer to a CONTEXT structure that receives the appropriate context of the specified thread. If the function succeeds, the return value is nonzero. Suspends the specified thread. A handle to the thread that is to be suspended. If the function succeeds, the return value is the thread's previous suspend count. If the function fails the return value is -1. Closes an open object handle. A valid handle to an open object. If the function succeeds, the return value is nonzero. Retrieves the address of an exported function or variable from the specified dynamic-link library (DLL). A handle to the DLL module that contains the function or variable. The function or variable name, or the function's ordinal value. If the function succeeds, the return value is the address of the exported function or variable. This function maps a specified executable module into the address space of the calling process. The executable module can be a .dll or an .exe file. The specified module may cause other modules to be mapped into the address space. Pointer to a null-terminated string that names the executable module. Must be null. Specifies the action to take when loading the module. Determines the location of a resource with the specified type and name in the specified module. A handle to the module whose portable executable file or an accompanying MUI file contains the resource. The name of the resource. The resource type. If the function succeeds, the return value is a handle to the specified resource's information block. Retrieves a handle that can be used to obtain a pointer to the first byte of the specified resource in memory. A handle to the module whose executable file contains the resource. A handle to the resource to be loaded. If the function succeeds, the return value is a handle to the data associated with the resource. Retrieves the process identifier of the specified process. A handle to the process. The handle must have the PROCESS_QUERY_INFORMATION or PROCESS_QUERY_LIMITED_INFORMATION access right. Returns the identifier of the process as a Uint Retrieves certain properties of an object handle. A handle to an object whose information is to be retrieved. A pointer to a variable that receives a set of bit flags that specify properties of the object handle or 0. The following values are defined. If the function succeeds, the return value is true. Retrieves a module handle for the specified module. The module must have been loaded by the calling process. The name of the loaded module (either a .dll or .exe file). If the function succeeds, the return value is a handle to the specified module. The ZwQueryInformationThread routine retrieves information about the specified thread. Handle to the thread object. The type of thread information to be retrieved. Pointer to a buffer supplied by the caller. The size, in bytes, of the buffer pointed to by threadinfo. A pointer to a variable in which the routine returns the size of the requested information. ZwQueryInformationThread returns STATUS_SUCCESS on success, or the appropriate NTSTATUS error code on failure. Retrieves a handle for each module in the specified process. A handle to the process. An array that receives the list of module handles. The size of the lphModule array, in bytes. The number of bytes required to store all module handles in the lphModule array. The filter criteria. If the function succeeds, the return value is nonzero. Retrieves the fully qualified path for the file containing the specified module. A handle to the process that contains the module. A handle to the module. A pointer to a buffer that receives the fully qualified path to the module. The size of the lpFilename buffer, in characters. If the function succeeds, the return value specifies the length of the string copied to the buffer. Maintains a list of loaded DLLs. The name of the image. The path used to locate the image if the name provided cannot be found. If the function succeeds, the return value is a pointer to a LOADED_IMAGE structure. Locates and returns the load configuration data of an image. A pointer to a LOADED_IMAGE structure. A pointer to an IMAGE_LOAD_CONFIG_DIRECTORY32 If the function succeeds, the return value is TRUE. Locates and returns the load configuration data of an image. A pointer to a LOADED_IMAGE structure. A pointer to an IMAGE_LOAD_CONFIG_DIRECTORY64 If the function succeeds, the return value is TRUE. Locates and returns the load configuration data of an image. A Loaded_Image structure. A pointer to an IMAGE_LOAD_CONFIG_DIRECTORY32 If the function succeeds, the return value is TRUE. Locates and returns the load configuration data of an image. A Loaded_Image structure. A pointer to an IMAGE_LOAD_CONFIG_DIRECTORY64 If the function succeeds, the return value is TRUE. Maps an image and preloads data from the mapped file. The file name of the image (executable file or DLL) that is loaded. The path used to locate the image if the name provided cannot be found. A pointer to a LOADED_IMAGE structure that receives information about the image after it is loaded. True if the file is a DLL, false if the file is an EXE. Boolean for the access mode. If the function succeeds, the return value is TRUE. Constructor. Constructor to be used when creating an object that inherits from an ErcCore object. The ErcCore object to be inherited from. Changes the working directory in both the XML file and associated ErcCore object Sets the standard pattern file path. Any pattern can replace the standard pattern when searching however the new pattern must be written to a file and the file path set here. The filepath of the new standard pattern file Sets the extended pattern file path. Any pattern can replace the extended pattern when searching however the new pattern must be written to a file and the file path set here. The filepath of the new extended pattern file Sets the name of the author for use when outputing results to disk. String containing the name of the author Sets the error log file to a user specified filepath. The new error log filepath. Logs events to the error log path in the XML file. This file is only appended to and never replaced. The exception to log Converts a x64 pointer into a x86 pointer. 64bit pointer to be converted Retruns a byte array 4 bytes long containing the modified pointer A basic object which contains a generic type and exception. A generic type Generic Type. Exception to be logged by LogEvent(). Base constructor. The ErcCore object to inherit from. Base constructor with a custom location for exceptions to be logged. The ErcCore object to inherit from. The location to log exceptions. Logs an event to the ErrorLogFile value. Override of the ToString method. Returns a string containing values relevant to the object. A string containing information about the object. Enum containing types of machine architectures. Native. x86. Itanium. x64. Type is unknown or unset. IMAGE_DOS_HEADER. A pointer to the IMAGE_NT_HEADER. IMAGE_FILE_HEADER. See https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-image_file_header Machine NumberOfSections TimeDateStamp PointerToSymbolTable NumberOfSymbols SizeOfOptionalHeader Characteristics IMAGE_NT_HEADER 32 bit variant. See https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-_image_nt_headers Signature FileHeader OptionalHeader IMAGE_NT_HEADER 64 bit variant. See https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-_image_nt_headers Signature FileHeader OptionalHeader IMAGE_DATA_DIRECTORY. See https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-image_data_directory VirtualAddress. Size. IMAGE_OPTIONAL_HEADER 32 bit variant. See https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-_image_optional_header Magic MajorLinkerVersion MinorLinkerVersion SizeOfCode SizeOfInitializedData SizeOfUninitializedData AddressOfEntryPoint BaseOfCode BaseOfData ImageBase SectionAlignment FileAlignment MajorOperatingSystemVersion MinorOperatingSystemVersion MajorImageVersion MinorImageVersion MajorSubsystemVersion MinorSubsystemVersion Win32VersionValue SizeOfImage SizeOfHeaders CheckSum Subsystem DllCharacteristics SizeOfStackReserve SizeOfStackCommit SizeOfHeapReserve SizeOfHeapCommit LoaderFlags NumberOfRvaAndSizes ExportTable ImportTable ResourceTable ExceptionTable CertificateTable BaseRelocationTable Debug Architecture GlobalPtr TLSTable LoadConfigTable BoundImport IAT DelayImportDescriptor CLRRuntimeHeader Reserved IMAGE_OPTIONAL_HEADER 64 bit variant. See https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-_image_optional_header Magic MajorLinkerVersion MinorLinkerVersion SizeOfCode SizeOfInitializedData SizeOfUninitializedData AddressOfEntryPoint BaseOfCode ImageBase SectionAlignment FileAlignment MajorOperatingSystemVersion MinorOperatingSystemVersion MajorImageVersion MinorImageVersion MajorSubsystemVersion MinorSubsystemVersion Win32VersionValue SizeOfImage SizeOfHeaders CheckSum Subsystem DllCharacteristics SizeOfStackReserve SizeOfStackCommit SizeOfHeapReserve SizeOfHeapCommit LoaderFlags NumberOfRvaAndSizes ExportTable ImportTable ResourceTable ExceptionTable CertificateTable BaseRelocationTable Debug Architecture GlobalPtr TLSTable LoadConfigTable BoundImport IAT DelayImportDescriptor CLRRuntimeHeader Reserved Image Option Header Magic Type. IMAGE_NT_OPTIONAL_HDR32_MAGIC IMAGE_NT_OPTIONAL_HDR64_MAGIC Image Option Header SubSystem Type. IMAGE_SUBSYSTEM_UNKNOWN IMAGE_SUBSYSTEM_NATIVE IMAGE_SUBSYSTEM_WINDOWS_GUI IMAGE_SUBSYSTEM_WINDOWS_CUI IMAGE_SUBSYSTEM_POSIX_CUI IMAGE_SUBSYSTEM_WINDOWS_CE_GUI IMAGE_SUBSYSTEM_EFI_APPLICATION IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER IMAGE_SUBSYSTEM_EFI_ROM IMAGE_SUBSYSTEM_XBOX IMAGE_LOAD_CONFIG_DIRECTORY32. See https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-_image_load_config_directory32 Size TimeDateStamp MajorVersio MinorVersion GlobalFlagsClear GlobalFlagsSet CriticalSectionDefaultTimeout DeCommitFreeBlockThreshold DeCommitTotalFreeThreshold LockPrefixTable MaximumAllocationSize VirtualMemoryThreshold ProcessHeapFlags ProcessAffinityMask CSDVersion DependentLoadFlags EditList SecurityCookie SEHandlerTable SEHandlerCount GuardCFCheckFunctionPointer GuardCFDispatchFunctionPointer GuardCFFunctionTable GuardCFFunctionCount GuardFlags CodeIntegrity GuardAddressTakenIatEntryTable GuardAddressTakenIatEntryCount GuardLongJumpTargetTable GuardLongJumpTargetCount DynamicValueRelocTable CHPEMetadataPointer GuardRFFailureRoutine GuardRFFailureRoutineFunctionPointer DynamicValueRelocTableOffset DynamicValueRelocTableSection Reserved2 GuardRFVerifyStackPointerFunctionPointer HotPatchTableOffset Reserved3 EnclaveConfigurationPointer VolatileMetadataPointer IMAGE_LOAD_CONFIG_DIRECTORY32. See https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-_image_load_config_directory64 Size TimeDateStamp MajorVersion MinorVersion GlobalFlagsClear GlobalFlagsSet CriticalSectionDefaultTimeout DeCommitFreeBlockThreshold DeCommitTotalFreeThreshold LockPrefixTable MaximumAllocationSize VirtualMemoryThreshold ProcessAffinityMask ProcessHeapFlags CSDVersion DependentLoadFlags EditList SecurityCookie SEHandlerTable SEHandlerCount GuardCFCheckFunctionPointer GuardCFDispatchFunctionPointer GuardCFFunctionTable GuardCFFunctionCount GuardFlags CodeIntegrity GuardAddressTakenIatEntryTable GuardAddressTakenIatEntryCount GuardLongJumpTargetTable GuardLongJumpTargetCount DynamicValueRelocTable CHPEMetadataPointer GuardRFFailureRoutine GuardRFFailureRoutineFunctionPointer DynamicValueRelocTableOffset DynamicValueRelocTableSection Reserved2 GuardRFVerifyStackPointerFunctionPointer HotPatchTableOffset Reserved3 EnclaveConfigurationPointer VolatileMetadataPointer IMAGE_LOAD_CONFIG_CODE_INTEGRITY. Flags Catalog CatalogOffset Reserved LOADED_IMAGE. See https://docs.microsoft.com/en-us/windows/win32/api/dbghelp/ns-dbghelp-_loaded_image ModuleName hFile MappedAddress FileHeader LastRvaSection NumberOfSections Sections Characteristics fSystemImage fDOSImage fReadOnly Version Links SizeOfImage Describes an entry in a doubly linked list or serves as the header for such a list. See https://docs.microsoft.com/en-us/windows/win32/api/ntdef/ns-ntdef-_list_entry Flink points to the next entry in the list. Blink points to the previous entry in the list. AllocationProtect. PAGE_EXECUTE PAGE_EXECUTE_READ PAGE_EXECUTE_READWRITE PAGE_EXECUTE_WRITECOPY PAGE_NOACCESS PAGE_READONLY PAGE_READWRITE PAGE_WRITECOPY PAGE_GUARD PAGE_NOCACHE PAGE_WRITECOMBINE StateEnum MEM_COMMIT MEM_FREE MEM_RESERVE TypeEnum MEM_IMAGE MEM_MAPPED MEM_PRIVATE MEMORY_BASIC_INFORMATION32. See https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-_memory_basic_information BaseAddress AllocationBase AllocationProtec RegionSize State Protect Type MEMORY_BASIC_INFORMATION32. See https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-_memory_basic_information BaseAddress AllocationBase AllocationProtect __alignment1 RegionSize State Protect Type __alignment2 ProcessAccessFlags All Terminate CreateThread VirtualMemoryOperation VirtualMemoryRead VirtualMemoryWrite DuplicateHandle CreateProcess SetQuota SetInformation QueryInformation QueryLimitedInformation Synchronize LoadLibraryFlags None DONT_RESOLVE_DLL_REFERENCES LOAD_IGNORE_CODE_AUTHZ_LEVEL LOAD_LIBRARY_AS_DATAFILE LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE LOAD_LIBRARY_AS_IMAGE_RESOURCE LOAD_LIBRARY_SEARCH_APPLICATION_DIR LOAD_LIBRARY_SEARCH_DEFAULT_DIRS LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR LOAD_LIBRARY_SEARCH_SYSTEM32 LOAD_LIBRARY_SEARCH_USER_DIRS LOAD_WITH_ALTERED_SEARCH_PATH Enum to specify access level required when accessing a thread. TERMINATE SUSPEND_RESUME GET_CONTEXT SET_CONTEXT SET_INFORMATION QUERY_INFORMATION SET_THREAD_TOKEN IMPERSONATE DIRECT_IMPERSONATION All_ACCESS CONTEXT_FLAGS CONTEXT_i386 CONTEXT_i486 CONTEXT_CONTROL CONTEXT_INTEGER CONTEXT_SEGMENTS CONTEXT_FLOATING_POINT CONTEXT_DEBUG_REGISTERS CONTEXT_EXTENDED_REGISTERS CONTEXT_FULL CONTEXT_ALL x86 Save area data. See https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-_wow64_floating_save_area ControlWord StatusWord TagWord ErrorOffset ErrorSelector DataOffset DataSelector RegisterArea Cr0NpxState Structure for holding x86 register values. ContextFlags Dr0 Dr1 Dr2 Dr3 Dr6 Dr7 FloatSave SegGs SegFs SegEs SegDs Edi Esi Ebx Edx Ecx Eax Ebp Eip SegCs EFlags Esp SegSs ExtendedRegisters Overridden ToString method, returns register values for the current thread. String M128A High Low ToString Override Returns a String x64 Save area data. ControlWord StatusWord TagWord Reserved1 ErrorOpcode ErrorOffset ErrorSelector Reserved2 DataOffset DataSelector Reserved3 MxCsr MxCsr_Mask FloatRegisters XmmRegisters Reserved4 Structure for holding x64 register values. P1Home P2Home P3Home P4Home P5Home P6Home ContextFlags MxCsr SegCs SegDs SegEs SegFs SegGs SegSs EFlags Dr0 Dr1 Dr2 Dr3 Dr6 Dr7 Rax Rcx Rdx Rbx Rsp Rbp Rsi Rdi R8 R9 R10 R11 R12 R13 R14 R15 Rip DUMMYUNIONNAME VectorRegister VectorControl DebugControl LastBranchToRip LastBranchFromRip LastExceptionToRip LastExceptionFromRip Overridden ToString method, returns register values for the current thread. String Register information Register name. Register value. Register Offset. String offset. Buffer size. Thread ID. Overwritten. ThreadBasicInformation ExitStatus TebBaseAdress Identifiers AffinityMask Priority BasePriority ClientID ProcessID ThreadID Thread Environment Block. CurrentSehFrame TopOfStack BottomOfStack SubSystemTeb FiberData ArbitraryDataSlot Teb EnvironmentPointer Identifiers RpcHandle Tls Peb LastErrorNumber CriticalSectionsCount CsrClientThread Win32ThreadInfo Win32ClientInfo WoW64Reserved CurrentLocale FpSoftwareStatusRegister SystemReserved1 ExceptionCode ActivationContextStack SpareBytes SystemReserved2 GdiTebBatch GdiRegion GdiPen GdiBrush RealProcessId RealThreadId GdiCachedProcessHandle GdiClientProcessId GdiClientThreadId GdiThreadLocalInfo UserReserved1 GlReserved1 LastStatusValue StaticUnicodeString DeallocationStack TlsSlots TlsLinks Vdm RpcReserved ThreadErrorMode Contains all information relating to a specific module. Module name. Module path. Module version. Module product. Memory protection of this module. Module base pointer. Module entry point. Module image base. Module size. Module supports ASLR. Module supports SafeSEH Module can be rebased. Module is DEP enabled. Module is an OS dll. Process where the module is loaded. Associated ErcCore object. Machine type of the module. An errpr was encountered whilst processing the module. Constructor for the ModuleInfo object. Takes (string)modules filepath (IntPtr)module handle (Process)Process from which the module is loaded Filepath of the module Handle to the module Process where the module is loaded An ErcCore object Searches for a string of bytes within a specific module. Takes a byte array to be searched for. A byte array to be searched for Returns ERC_Result of pointers to the search term Override of the ToString method. Provides a data associated with the module. A string containing relevant data. Contains information needed for the associated functions relating to the process. Name of the process. Process description. Path for the projects main module. Process ID. Handle for the process. .Net Process object for this process The machine type the process runs on. Eg. x86 or x64 A list containing ModuleInfo objects associuted with the process. /// A list containing ThreadInfo objects associuted with the process. /// Constructor for the Process_Info object, requires an ERC_Core object and a Process. An ErcCore object The process to gather information from Constructor for the Process_Info object, requires an ERC_Core object and a Process. An ErcCore object The handle for the process to gather information from Constructor to use when inheriting from ProcessInfo. The object to inherit from Gets a list of running processes on the host and removes unusable processes (such as system processes etc) An ErcCore object Returns an ErcResult containing a list of all supported processes Gets a list of running processes on the host and removes unusable processes. An ErcCore object The computer from which to read the list of processes. Can be either the hostname or IP address. Returns an ErcResult containing a list of all supported processes Returns a list of files loaded by the current process as List String Returns an ErcResult containing a Dictionary of module names and the associated handles Identifies if a process is 64bit or 32 bit, returns true for 64bit and false for 32bit. The process to be used Returns true if the process is 64bit and false if it is not. Identifies memory regions occupied by the current process and populates the associated list with the Process_Info object. Private function called from Search_Memory. Searches memory regions populated by the process for specific strings. Takes a byte array as input to be searched for Returns a list of IntPtr for each instance found. Private function called from Search_Memory. Searches memory regions populated by the process for specific strings. Takes a byte array as input to be searched for Takes a byte array of values used to disqualify pointers Returns a list of IntPtr for each instance found. Searches all memory associated with a given process and associated modules for POP X POP X RET instructions. Passing a list of module paths or names will exclude those modules from the search. Takes a list of module names to be excluded from the search Returns an ERC_Result containing a dictionary of pointers and the main module in which they were found Searches all memory associated with a given process and associated modules for POP X POP X RET instructions. Passing a list of module paths or names will exclude those modules from the search. Takes a list of module names to be excluded from the search Takes a byte array of values used to disqualify pointers Returns an ERC_Result containing a dictionary of pointers and the main module in which they were found Searches all memory (the process and associated DLLs) for a specific string or byte array. Strings can be passed as ASCII, Unicode, UTF7 or UTF8. Specific modules can be exclude through passing a Listof strings containing module names or paths. 0 = search term is in bytes\n1 = search term is in unicode\n2 = search term is in ASCII\n3 = Search term is in UTF8\n4 = Search term is in UTF7\n5 = Search term is in UTF32 Byte array to be searched for (optional) String to be searched for (optional) Modules to be excluded from the search (optional) Returns an ERC_Result containing pointers to all instances of the search query. Searches all memory (the process and associated DLLs) for a specific string or byte array. Strings can be passed as ASCII, Unicode, UTF7 or UTF8. Specific modules can be exclude through passing a Listof strings containing module names or paths. 0 = search term is in bytes\n1 = search term is in unicode\n2 = search term is in ASCII\n3 = Search term is in UTF8\n4 = Search term is in UTF7\n5 = Search term is in UTF32 Takes a byte array of values used to disqualify pointers Byte array to be searched for (optional) String to be searched for (optional) Modules to be excluded from the search (optional) Returns an ERC_Result containing pointers to all instances of the search query. Searches all modules loaded by a process for a specific string or byte array. Strings can be passed as ASCII, Unicode, UTF7 or UTF8. Search can be limited to specific modules through passing a List of strings containing module names or paths. 0 = search term is in bytes\n1 = search term is in unicode\n2 = search term is in ASCII\n3 = Search term is in UTF8\n4 = Search term is in UTF7\n5 = Search term is in UTF32 Takes a byte array of values used to disqualify pointers Byte array to be searched for (optional) String to be searched for (optional) Modules to be included in the search (optional) Modules to be excluded from the search (optional) Returns an ERC_Result containing pointers to all instances of the search query.> Searches process registers and identifies pointers to buffers in memory containing a non repeating pattern. Functionality to identify SEH overwrites not yet implements. (Optional) 0 = search term is system default\n1 = search term is in unicode\n2 = search term is in ASCII\n3 = Search term is in UTF8\n4 = Search term is in UTF7\n5 = Search term is in UTF32 (Optional) Include additional characters in the pattern (!#$%^ etc) in the to be searched Returns a ERC_Result containing a List of RegisterOffset Private function, BoyerMoore string search algorithm modified to search for sets of bytes in a byte array. Takes two byte arrays, array to be searched and array to search for. Creates a list of modules to exclude from a search of memory. Returns an ErcResult containing a list of stringss Override of the ToString method. Returns information about the process in a pleasantly formatted string A string Returns a list of module handles associated with the process. Returns a dictionary containing the handle and path of each module Gets the list of ModuleInfo objects associated with the current process. Returns an ErcResult containing a list of ModuleInfo objects Gets the list of ThreadInfo objects associated with the current process. Returns an ErcResult containing a list of ThreadInfo objects Reads process memory from a specific address for a set number of bytes. The address to start reading from. Number of bytes to read. Returns a bytes array containing the specified contents of process memory. Stores information about the current thread. A handle for the current thread. The ID number of the current thread. x86 CPU Register values. x64 CPU Register values. Gets the register values of a thread and populates the CONTEXT structs. Should only be used on a suspended thread, results on an active thread are unreliable. Returns an ErcResult, the return value can be ignored, the object should only be checked for error values Gets the current SEH chain for the process. Returns a list of IntPtr containing the SEH chain Gets the Thread environment block of the current thread. Returns a TEB struct Gets information specific to the current thread and returns it as a string. Returns a string ================================================ FILE: ERC/ERC/ERCException.cs ================================================ using System; using System.Runtime.Serialization; namespace ERC { /// /// Custom exception handler. /// [Serializable] public class ERCException : Exception { /// /// Constructor for the ERCException class. /// /// The message associated with the Exception public ERCException(string message) : base(message) { } /// /// Creates a serializable exception. /// /// Stores all the data needed to serialize or deserialize an object. /// Describes the source and destination of a given serialized stream, and provides an additional caller-defined context. protected ERCException(SerializationInfo info, StreamingContext ctxt) : base(info, ctxt) { } } } ================================================ FILE: ERC/ERC/ERC_Core.cs ================================================ using System; using System.IO; using System.Text; using System.Runtime.InteropServices; using System.Reflection; using System.Xml; using System.ComponentModel; using ERC.Structures; namespace ERC { #region ErcCore /// /// A single instance of this object should be instantiated at a minimum. It is used for storing global variables such as the working directory etc. /// public class ErcCore { #region Class Variables /// /// The current version of the ERC.Net library /// public string ErcVersion { get; } /// /// The directory where output files will be saved. /// public string WorkingDirectory { get; internal set; } /// /// The Author to be credited in output files. /// public string Author { get; set; } /// /// Path of the current ERC_Config.xml file. /// private string ConfigPath { get; set; } /// /// Path where error details should be logged. /// public string SystemErrorLogPath { get; set; } /// /// Path to the file containing the standard pattern to be used. /// public string PatternStandardPath { get; set; } /// /// Path to the file containing the extended pattern to be used. /// public string PatternExtendedPath { get; set; } private Exception SystemError { get; set; } private XmlDocument ErcConfig = new XmlDocument(); #endregion #region DLL Imports /// /// Opens an existing local process object. /// /// The access to the process object. This access right is checked against the security descriptor for the process. /// If this value is TRUE, processes created by this process will inherit the handle. Otherwise, the processes do not inherit this handle. /// The identifier of the local process to be opened. /// If the function succeeds, the return value is an open handle to the specified process. [DllImport("kernel32.dll", SetLastError = true)] internal static extern IntPtr OpenProcess(ProcessAccessFlags dwDesiredAccess, bool bInheritHandle, int dwProcessId); /// /// Reads data from an area of memory in a specified process. The entire area to be read must be accessible or the operation fails. /// /// A handle to the process with memory that is being read. /// A pointer to the base address in the specified process from which to read. /// A pointer to a buffer that receives the contents from the address space of the specified process. /// The number of bytes to be read from the specified process. /// A pointer to a variable that receives the number of bytes transferred into the specified buffer. /// If the function succeeds, the return value is nonzero. [DllImport("kernel32.dll", SetLastError = true, CallingConvention = CallingConvention.StdCall)] internal static extern int ReadProcessMemory(IntPtr Handle, IntPtr Address, [Out] byte[] Arr, int Size, out int BytesRead); /// /// Retrieves information about a range of pages within the virtual address space of a specified 32 bit process. /// /// A handle to the process whose memory information is queried. /// A pointer to the base address of the region of pages to be queried. /// A pointer to a MEMORY_BASIC_INFORMATION32 structure in which information about the specified page range is returned. /// The size of the buffer pointed to by the lpBuffer parameter, in bytes. /// The return value is the actual number of bytes returned in the information buffer. [DllImport("kernel32.dll", SetLastError = true, EntryPoint = "VirtualQueryEx")] internal static extern int VirtualQueryEx32(IntPtr hProcess, IntPtr lpAddress, out MEMORY_BASIC_INFORMATION32 lpBuffer, uint dwLength); /// /// Retrieves information about a range of pages within the virtual address space of a specified 64 bit process. /// /// A handle to the process whose memory information is queried. /// A pointer to the base address of the region of pages to be queried. /// A pointer to a MEMORY_BASIC_INFORMATION64 structure in which information about the specified page range is returned. /// The size of the buffer pointed to by the lpBuffer parameter, in bytes. /// The return value is the actual number of bytes returned in the information buffer. [DllImport("kernel32.dll", SetLastError = true, EntryPoint = "VirtualQueryEx")] internal static extern int VirtualQueryEx64(IntPtr hProcess, IntPtr lpAddress, out MEMORY_BASIC_INFORMATION64 lpBuffer, uint dwLength); /// /// Determines whether the specified process is running under WOW64 or an Intel64 of x64 processor. /// /// A handle to the process. /// A pointer to a value that is set to TRUE if the process is running under WOW64 on an Intel64 or x64 processor. /// If the function succeeds, the return value is a nonzero value. [DllImport("kernel32.dll", SetLastError = true, CallingConvention = CallingConvention.Winapi)] [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool IsWow64Process([In] IntPtr process, [Out] out bool wow64Process); /// /// Opens an existing thread object. /// /// The access to the thread object. /// If this value is TRUE, processes created by this process will inherit the handle. /// The identifier of the thread to be opened. /// If the function succeeds, the return value is an open handle to the specified thread. [DllImport("kernel32.dll", SetLastError = true)] internal static extern IntPtr OpenThread(ThreadAccess dwDesiredAccess, bool bInheritHandle, uint dwThreadId); /// /// Retrieves the context of the specified 32 bit thread. /// /// A handle to the thread whose context is to be retrieved. /// A pointer to a CONTEXT structure that receives the appropriate context of the specified thread. /// If the function succeeds, the return value is nonzero. [DllImport("kernel32.dll", SetLastError = true, EntryPoint = "GetThreadContext")] internal static extern bool GetThreadContext32(IntPtr hThread, ref CONTEXT32 lpContext); /// /// Retrieves the context of the specified WOW64 thread. /// /// A handle to the thread whose context is to be retrieved. /// A pointer to a CONTEXT structure that receives the appropriate context of the specified thread. /// If the function succeeds, the return value is nonzero. [DllImport("kernel32.dll", SetLastError = true)] internal static extern bool Wow64GetThreadContext(IntPtr hthread, ref CONTEXT32 lpContext); /// /// Retrieves the context of the specified 64 bit thread. /// /// A handle to the thread whose context is to be retrieved. /// A pointer to a CONTEXT structure that receives the appropriate context of the specified thread. /// If the function succeeds, the return value is nonzero. [DllImport("kernel32.dll", SetLastError = true, EntryPoint = "GetThreadContext")] internal static extern bool GetThreadContext64(IntPtr hThread, ref CONTEXT64 lpContext); /// /// Suspends the specified thread. /// /// A handle to the thread that is to be suspended. /// If the function succeeds, the return value is the thread's previous suspend count. If the function fails the return value is -1. [DllImport("kernel32.dll", SetLastError= true)] internal static extern int SuspendThread(IntPtr hThread); /// /// Closes an open object handle. /// /// A valid handle to an open object. /// If the function succeeds, the return value is nonzero. [DllImport("kernel32.dll", SetLastError = true)] internal static extern bool CloseHandle(IntPtr hObject); /// /// Retrieves the address of an exported function or variable from the specified dynamic-link library (DLL). /// /// A handle to the DLL module that contains the function or variable. /// The function or variable name, or the function's ordinal value. /// If the function succeeds, the return value is the address of the exported function or variable. [DllImport("kernel32.dll", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] internal static extern IntPtr GetProcAddress(IntPtr hModule, string procName); /// /// This function maps a specified executable module into the address space of the calling process. The executable module can be a .dll or an .exe file. The specified module may cause other modules to be mapped into the address space. /// /// Pointer to a null-terminated string that names the executable module. /// Must be null. /// Specifies the action to take when loading the module. /// [DllImport("kernel32.dll", SetLastError = true)] internal static extern IntPtr LoadLibraryEx(string lpFileName, IntPtr hReservedNull, LoadLibraryFlags dwFlags); /// /// Determines the location of a resource with the specified type and name in the specified module. /// /// A handle to the module whose portable executable file or an accompanying MUI file contains the resource. /// The name of the resource. /// The resource type. /// If the function succeeds, the return value is a handle to the specified resource's information block. [DllImport("kernel32.dll", SetLastError = true, EntryPoint = "FindResourceA")] internal static extern IntPtr FindResouce(IntPtr hModule, ref string resName, ref string resType); /// /// Retrieves a handle that can be used to obtain a pointer to the first byte of the specified resource in memory. /// /// A handle to the module whose executable file contains the resource. /// A handle to the resource to be loaded. /// If the function succeeds, the return value is a handle to the data associated with the resource. [DllImport("kernel32.dll", SetLastError = true)] internal static extern IntPtr LoadResource(IntPtr hModule, IntPtr hResInfo); /// /// Retrieves the process identifier of the specified process. /// /// A handle to the process. The handle must have the PROCESS_QUERY_INFORMATION or PROCESS_QUERY_LIMITED_INFORMATION access right. /// Returns the identifier of the process as a Uint [DllImport("kernel32.dll", SetLastError = true)] internal static extern uint GetProcessId(IntPtr handle); /// /// Retrieves certain properties of an object handle. /// /// A handle to an object whose information is to be retrieved. /// A pointer to a variable that receives a set of bit flags that specify properties of the object handle or 0. The following values are defined. /// If the function succeeds, the return value is true. [DllImport("kernel32.dll")] public static extern bool GetHandleInformation(IntPtr hObject, out uint lpdwFlags); /// /// Retrieves a module handle for the specified module. The module must have been loaded by the calling process. /// /// The name of the loaded module (either a .dll or .exe file). /// If the function succeeds, the return value is a handle to the specified module. [DllImport("user32.dll", EntryPoint = "GetModuleHandleW", SetLastError = true)] internal static extern IntPtr GetModuleHandle(string moduleName); /// /// The ZwQueryInformationThread routine retrieves information about the specified thread. /// /// Handle to the thread object. /// The type of thread information to be retrieved. /// Pointer to a buffer supplied by the caller. /// The size, in bytes, of the buffer pointed to by threadinfo. /// A pointer to a variable in which the routine returns the size of the requested information. /// ZwQueryInformationThread returns STATUS_SUCCESS on success, or the appropriate NTSTATUS error code on failure. [DllImport("ntdll.dll", SetLastError = true)] internal static extern uint ZwQueryInformationThread(IntPtr hwnd, int i, ref ThreadBasicInformation threadinfo, int length, IntPtr bytesread); /// /// Retrieves a handle for each module in the specified process. /// /// A handle to the process. /// An array that receives the list of module handles. /// The size of the lphModule array, in bytes. /// The number of bytes required to store all module handles in the lphModule array. /// The filter criteria. /// If the function succeeds, the return value is nonzero. [DllImport("psapi.dll", SetLastError = true)] internal static extern bool EnumProcessModulesEx(IntPtr hProcess, [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.U4)] [In][Out] IntPtr[] lphModule, int cb, [MarshalAs(UnmanagedType.U4)] out int lpcbNeeded, uint dwFilterFlag); /// /// Retrieves the fully qualified path for the file containing the specified module. /// /// A handle to the process that contains the module. /// A handle to the module. /// A pointer to a buffer that receives the fully qualified path to the module. /// The size of the lpFilename buffer, in characters. /// If the function succeeds, the return value specifies the length of the string copied to the buffer. [DllImport("psapi.dll", SetLastError = true)] internal static extern uint GetModuleFileNameEx(IntPtr hProcess, IntPtr hModule, [Out] StringBuilder lpBaseName, [In] [MarshalAs(UnmanagedType.U4)] int nSize); /// /// Maintains a list of loaded DLLs. /// /// The name of the image. /// The path used to locate the image if the name provided cannot be found. /// If the function succeeds, the return value is a pointer to a LOADED_IMAGE structure. [DllImport("Imagehlp.dll", SetLastError = true)] internal static extern IntPtr ImageLoad(string DllName, string DllPath); /// /// Locates and returns the load configuration data of an image. /// /// A pointer to a LOADED_IMAGE structure. /// A pointer to an IMAGE_LOAD_CONFIG_DIRECTORY32 /// If the function succeeds, the return value is TRUE. [DllImport("Imagehlp.dll", SetLastError = true, EntryPoint = "GetImageConfigInformation")] internal static extern bool GetImageConfigInformation32(IntPtr dllptr, out IMAGE_LOAD_CONFIG_DIRECTORY32 ImageConfigDir32); /// /// Locates and returns the load configuration data of an image. /// /// A pointer to a LOADED_IMAGE structure. /// A pointer to an IMAGE_LOAD_CONFIG_DIRECTORY64 /// If the function succeeds, the return value is TRUE. [DllImport("Imagehlp.dll", SetLastError = true, EntryPoint = "GetImageConfigInformation")] internal static extern bool GetImageConfigInformation64(IntPtr dllptr, out IMAGE_LOAD_CONFIG_DIRECTORY64 ImageConfigDir64); /// /// Locates and returns the load configuration data of an image. /// /// A Loaded_Image structure. /// A pointer to an IMAGE_LOAD_CONFIG_DIRECTORY32 /// If the function succeeds, the return value is TRUE. [DllImport("Imagehlp.dll", SetLastError = true, EntryPoint = "GetImageConfigInformation")] internal static extern bool GetImageConfigInformation32(ref LOADED_IMAGE loadedImage, ref IMAGE_LOAD_CONFIG_DIRECTORY32 ImageConfigDir32); /// /// Locates and returns the load configuration data of an image. /// /// A Loaded_Image structure. /// A pointer to an IMAGE_LOAD_CONFIG_DIRECTORY64 /// If the function succeeds, the return value is TRUE. [DllImport("Imagehlp.dll", SetLastError = true, EntryPoint = "GetImageConfigInformation")] internal static extern bool GetImageConfigInformation64(ref LOADED_IMAGE loadedImage, ref IMAGE_LOAD_CONFIG_DIRECTORY64 ImageConfigDir64); /// /// Maps an image and preloads data from the mapped file. /// /// The file name of the image (executable file or DLL) that is loaded. /// The path used to locate the image if the name provided cannot be found. /// A pointer to a LOADED_IMAGE structure that receives information about the image after it is loaded. /// True if the file is a DLL, false if the file is an EXE. /// Boolean for the access mode. /// If the function succeeds, the return value is TRUE. [DllImport("Imagehlp.dll", SetLastError = true)] internal static extern int MapAndLoad(string ImageName, string DllPath, out LOADED_IMAGE loadedImage, bool Dll, bool readOnly); /// /// Takes a snapshot of the specified processes, as well as the heaps, modules, and threads used by these processes. /// /// The portions of the system to be included in the snapshot. /// The process identifier of the process to be included in the snapshot. This parameter can be zero to indicate the current process. This parameter is used when the TH32CS_SNAPHEAPLIST, TH32CS_SNAPMODULE, TH32CS_SNAPMODULE32, or TH32CS_SNAPALL value is specified. Otherwise, it is ignored and all processes are included in the snapshot. /// If the function succeeds, it returns an open handle to the specified snapshot. [DllImport("kernel32", SetLastError = true, CallingConvention = CallingConvention.StdCall)] internal static extern IntPtr CreateToolhelp32Snapshot([In] Structures.SnapshotFlags dwFlags, [In] uint th32ProcessID); /// /// Retrieves information about the first process encountered in a system snapshot. /// /// A handle to the snapshot returned from a previous call to the CreateToolhelp32Snapshot function. /// A pointer to a PROCESSENTRY32 structure. /// Returns TRUE if the first entry of the process list has been copied to the buffer or FALSE otherwise. [DllImport("kernel32", SetLastError = true, CallingConvention = CallingConvention.StdCall)] internal static extern bool Process32First([In] IntPtr hSnapshot, ref PROCESSENTRY32 lppe); /// /// Retrieves information about the next process recorded in a system snapshot. /// /// A handle to the snapshot returned from a previous call to the CreateToolhelp32Snapshot function. /// A pointer to a PROCESSENTRY32 structure. /// Returns TRUE if the next entry of the process list has been copied to the buffer or FALSE otherwise. [DllImport("kernel32", SetLastError = true, CallingConvention = CallingConvention.StdCall)] internal static extern bool Process32Next([In] IntPtr hSnapshot, ref PROCESSENTRY32 lppe); /// /// Retrieves information about the first heap that has been allocated by a specified process. /// /// A handle to the snapshot returned from a previous call to the CreateToolhelp32Snapshot function. /// A pointer to a HEAPLIST32 structure. /// Returns TRUE if the first entry of the heap list has been copied to the buffer or FALSE otherwise. [DllImport("kernel32.dll", SetLastError = true, CallingConvention = CallingConvention.StdCall)] internal static extern bool Heap32ListFirst(IntPtr hSnapshot, ref HEAPLIST32 lphl); /// /// Retrieves information about the next heap that has been allocated by a specified process. /// /// A handle to the snapshot returned from a previous call to the CreateToolhelp32Snapshot function. /// A pointer to a HEAPLIST32 structure. /// Returns TRUE if the first entry of the heap list has been copied to the buffer or FALSE otherwise. [DllImport("kernel32.dll", SetLastError = true, CallingConvention = CallingConvention.StdCall)] internal static extern bool Heap32ListNext(IntPtr hSnapshot, ref HEAPLIST32 lphl); /// /// Retrieves information about the first block of a heap that has been allocated by a process. /// /// A pointer to a HEAPENTRY32 structure. /// The identifier of the process context that owns the heap. /// The identifier of the heap to be enumerated. /// Returns TRUE if information for the first heap block has been copied to the buffer or FALSE otherwise. [DllImport("kernel32.dll", SetLastError = true, CallingConvention = CallingConvention.StdCall)] internal static extern bool Heap32First(ref HEAPENTRY32 heapentry32, uint processID, IntPtr heapID); /// /// Retrieves information about the next block of a heap that has been allocated by a process. /// /// A pointer to a HEAPENTRY32 structure. /// Returns TRUE if information about the next block in the heap has been copied to the buffer or FALSE otherwise. [DllImport("kernel32.dll", SetLastError = true, CallingConvention = CallingConvention.StdCall)] internal static extern bool Heap32Next(ref HEAPENTRY32 heapentry32); #endregion #region Constructor /// /// Constructor. /// public ErcCore() { WorkingDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().CodeBase); WorkingDirectory = WorkingDirectory.Remove(0, 6); WorkingDirectory += "\\"; ConfigPath = Path.Combine(WorkingDirectory, "ERC_Config.XML"); PatternStandardPath = ""; PatternExtendedPath = ""; SystemErrorLogPath = Path.Combine(WorkingDirectory, "System_Error.LOG"); ErcVersion = "ERC.Xdbg_32-2.0.3"; //Uncomment for 32bit. //ErcVersion = "ERC.Xdbg_64-2.0.3"; //Uncomment for 64bit. bool configRead = false; while (configRead == false) { if (File.Exists(ConfigPath)) { try { ErcConfig.Load(ConfigPath); var singleNode = ErcConfig.DocumentElement.SelectNodes("//Working_Directory"); WorkingDirectory = singleNode[0].InnerText; singleNode = ErcConfig.DocumentElement.SelectNodes("//Author"); Author = singleNode[0].InnerText; singleNode = ErcConfig.DocumentElement.SelectNodes("//Standard_Pattern"); PatternStandardPath = singleNode[0].InnerText; singleNode = ErcConfig.DocumentElement.SelectNodes("//Extended_Pattern"); PatternExtendedPath = singleNode[0].InnerText; singleNode = ErcConfig.DocumentElement.SelectNodes("//Error_Log_File"); SystemErrorLogPath = singleNode[0].InnerText; configRead = true; ErcConfig = null; GC.Collect(); } catch (Exception e) { SystemError = e; BuildDefaultConfig(); } } else { BuildDefaultConfig(); } } if (PatternStandardPath == "") { PatternStandardPath = Path.Combine(WorkingDirectory, "Pattern_Standard"); if (!File.Exists(PatternStandardPath)) { var patternExt = Utilities.PatternTools.PatternCreate(20277, this, false); if (patternExt.Error != null) { patternExt.LogEvent(); Environment.Exit(1); } File.WriteAllText(PatternStandardPath, patternExt.ReturnValue); } } else { if (!File.Exists(PatternStandardPath)) { var patternExt = Utilities.PatternTools.PatternCreate(20277, this, false); if (patternExt.Error != null) { patternExt.LogEvent(); Environment.Exit(1); } File.WriteAllText(PatternStandardPath, patternExt.ReturnValue); } } if (PatternExtendedPath == "") { PatternExtendedPath = Path.Combine(WorkingDirectory, "Pattern_Extended"); if (!File.Exists(PatternExtendedPath)) { var patternExt = Utilities.PatternTools.PatternCreate(66923, this, true); if (patternExt.Error != null) { patternExt.LogEvent(); Environment.Exit(1); } File.WriteAllText(PatternExtendedPath, patternExt.ReturnValue); } } else { if (!File.Exists(PatternExtendedPath)) { var patternExt = Utilities.PatternTools.PatternCreate(66923, this, true); if (patternExt.Error != null) { patternExt.LogEvent(); Environment.Exit(1); } File.WriteAllText(PatternExtendedPath, patternExt.ReturnValue); } } } /// /// Constructor to be used when creating an object that inherits from an ErcCore object. /// /// The ErcCore object to be inherited from. protected ErcCore(ErcCore parent) { WorkingDirectory = parent.WorkingDirectory; Author = parent.Author; } private void BuildDefaultConfig() { string patternStandardPath = Path.Combine(WorkingDirectory, "Pattern_Standard"); string patternExtendedPath = Path.Combine(WorkingDirectory, "Pattern_Extended"); string systemErrorLogPath = Path.Combine(WorkingDirectory, "System_Error.LOG"); XmlDocument defaultConfig = new XmlDocument(); XmlDeclaration xmlDeclaration = defaultConfig.CreateXmlDeclaration("1.0", "UTF-8", null); XmlElement root = defaultConfig.DocumentElement; defaultConfig.InsertBefore(xmlDeclaration, root); XmlElement erc_xml = defaultConfig.CreateElement(string.Empty, "ERC.Net", Assembly.GetExecutingAssembly().GetName().Version.ToString()); defaultConfig.AppendChild(erc_xml); XmlElement parameters = defaultConfig.CreateElement(string.Empty, "Parameters", string.Empty); erc_xml.AppendChild(parameters); XmlElement workingDir = defaultConfig.CreateElement(string.Empty, "Working_Directory", string.Empty); XmlText text1 = defaultConfig.CreateTextNode(WorkingDirectory); workingDir.AppendChild(text1); parameters.AppendChild(workingDir); XmlElement author = defaultConfig.CreateElement(string.Empty, "Author", string.Empty); text1 = defaultConfig.CreateTextNode("No_Author_Set"); author.AppendChild(text1); parameters.AppendChild(author); XmlElement patternS = defaultConfig.CreateElement(string.Empty, "Standard_Pattern", string.Empty); text1 = defaultConfig.CreateTextNode(patternStandardPath); patternS.AppendChild(text1); parameters.AppendChild(patternS); XmlElement patternE = defaultConfig.CreateElement(string.Empty, "Extended_Pattern", string.Empty); text1 = defaultConfig.CreateTextNode(patternExtendedPath); patternE.AppendChild(text1); parameters.AppendChild(patternE); XmlElement errorlog = defaultConfig.CreateElement(string.Empty, "Error_Log_File", string.Empty); text1 = defaultConfig.CreateTextNode(systemErrorLogPath); errorlog.AppendChild(text1); parameters.AppendChild(errorlog); try { defaultConfig.Save(ConfigPath); } catch(Exception e) { SystemError = e; LogEvent(e); } } #endregion #region Variable Setters #region SetWorkingDirectory /// /// Changes the working directory in both the XML file and associated ErcCore object /// /// public void SetWorkingDirectory(string path) { if (Directory.Exists(path)) { if (!path.EndsWith("\\")) { path += "\\"; } XmlDocument xmldoc = new XmlDocument(); xmldoc.Load(ConfigPath); var singleNode = xmldoc.DocumentElement.SelectSingleNode("//Working_Directory"); singleNode.InnerText = path; xmldoc.Save(ConfigPath); WorkingDirectory = path; } else { throw new Exception("User Input Error: Value supplied for working directory is not a valid directory"); } } #endregion #region SetPatternStandardPath /// /// Sets the standard pattern file path. Any pattern can replace the standard pattern when searching however the new pattern must be written to a file and the file path set here. /// /// The filepath of the new standard pattern file public void SetPatternStandardPath(string path) { if (Directory.Exists(path)) { if (!path.EndsWith("\\")) { path += "\\"; } XmlDocument xmldoc = new XmlDocument(); xmldoc.Load(ConfigPath); var singleNode = xmldoc.DocumentElement.SelectSingleNode("//Standard_Pattern"); singleNode.InnerText = path; xmldoc.Save(ConfigPath); PatternStandardPath = path; } else { throw new Exception("User Input Error: Value supplied for the standard pattern path is not a valid directory"); } } #endregion #region SetPatternExtendedPath /// /// Sets the extended pattern file path. Any pattern can replace the extended pattern when searching however the new pattern must be written to a file and the file path set here. /// /// The filepath of the new extended pattern file public void SetPatternExtendedPath(string path) { if (Directory.Exists(path)) { if (!path.EndsWith("\\")) { path += "\\"; } XmlDocument xmldoc = new XmlDocument(); xmldoc.Load(ConfigPath); var singleNode = xmldoc.DocumentElement.SelectSingleNode("//Extended_Pattern"); singleNode.InnerText = path; xmldoc.Save(ConfigPath); PatternExtendedPath = path; } else { throw new Exception("User Input Error: Value supplied for the extended pattern path is not a valid directory"); } } #endregion #region SetAuthor /// /// Sets the name of the author for use when outputing results to disk. /// /// String containing the name of the author public void SetAuthor(string author) { XmlDocument xmldoc = new XmlDocument(); xmldoc.Load(ConfigPath); var singleNode = xmldoc.DocumentElement.SelectSingleNode("//Author"); singleNode.InnerText = author; xmldoc.Save(ConfigPath); Author = author; } #endregion #region SetSystemErrorLogFile /// /// Sets the error log file to a user specified filepath. /// /// The new error log filepath. public void SetErrorFile(string path) { if (File.Exists(path)) { SystemErrorLogPath = path; XmlDocument xmldoc = new XmlDocument(); xmldoc.Load(ConfigPath); var singleNode = xmldoc.DocumentElement.SelectSingleNode("//Error_Log_File"); singleNode.InnerText = path; xmldoc.Save(ConfigPath); SystemErrorLogPath = path; } else if (Directory.Exists(Path.GetDirectoryName(path))) { if (!path.EndsWith("\\")) { path += "\\"; } path += "System_Error.LOG"; File.Create(path); XmlDocument xmldoc = new XmlDocument(); xmldoc.Load(ConfigPath); var singleNode = xmldoc.DocumentElement.SelectSingleNode("//Error_Log_File"); singleNode.InnerText = path; xmldoc.Save(ConfigPath); } else { File.Create(WorkingDirectory + "System_Error.LOG"); XmlDocument xmldoc = new XmlDocument(); xmldoc.Load(ConfigPath); var singleNode = xmldoc.DocumentElement.SelectSingleNode("//Error_Log_File"); singleNode.InnerText = path; xmldoc.Save(ConfigPath); SystemErrorLogPath = path; } } #endregion #region LogEvent /// /// Logs events to the error log path in the XML file. This file is only appended to and never replaced. /// /// The exception to log public void LogEvent(Exception e) { using (StreamWriter sw = File.AppendText(SystemErrorLogPath)) { sw.WriteLine(e); } } #endregion #endregion #region X64toX32PointerModifier /// /// Converts a x64 pointer into a x86 pointer. /// /// 64bit pointer to be converted /// Retruns a byte array 4 bytes long containing the modified pointer internal static byte[] X64toX32PointerModifier(byte[] ptr64) { byte[] ptr32 = new byte[4]; Array.Copy(ptr64, 0, ptr32, 0, 4); return ptr32; } #endregion } #endregion #region ErcResult /// /// A basic object which contains a generic type and exception. /// /// A generic type public class ErcResult : ErcCore { /// /// Generic Type. /// public T ReturnValue { get; set; } /// /// Exception to be logged by LogEvent(). /// public Exception Error { get; set; } /// /// Base constructor. /// /// The ErcCore object to inherit from. public ErcResult(ErcCore core) : base(core) { SystemErrorLogPath = core.SystemErrorLogPath; } /// /// Base constructor with a custom location for exceptions to be logged. /// /// The ErcCore object to inherit from. /// The location to log exceptions. public ErcResult(ErcCore core, string errorFile) : base(core) { SystemErrorLogPath = errorFile; } /// /// Logs an event to the ErrorLogFile value. /// public void LogEvent() { using (StreamWriter sw = File.AppendText(base.SystemErrorLogPath)) { sw.WriteLine(Error + " TimeStamp: " + DateTime.Now); } } /// /// Override of the ToString method. Returns a string containing values relevant to the object. /// /// A string containing information about the object. public override string ToString() { string ret = ""; ret += "ErcResult Type = " + ReturnValue.GetType() + Environment.NewLine; if (Error != null) { ret += "ErcResult.Error = " + Error.ToString() + Environment.NewLine; } else { ret += "ErcResult.Error = NULL" + Environment.NewLine; } ret += "ErcResult.ErrorLogFile = " + SystemErrorLogPath + Environment.NewLine; return base.ToString(); } } #endregion #region Type Definitions #region MachineType /// /// Enum containing types of machine architectures. /// public enum MachineType { /// /// Native. /// [Description("Native")] Native = 0, /// /// x86. /// [Description("I386")] I386 = 0x014c, /// /// Itanium. /// [Description("Itanium")] Itanium = 0x0200, /// /// x64. /// [Description("x64")] x64 = 0x8664, /// /// Type is unknown or unset. /// [Description("Error")] error = -1 } #endregion namespace Structures { #region DLL Headers #region IMAGE_DOS_HEADER /// /// IMAGE_DOS_HEADER. /// [StructLayout(LayoutKind.Explicit)] public struct IMAGE_DOS_HEADER { /// /// A pointer to the IMAGE_NT_HEADER. /// [FieldOffset(60)] public int nt_head_ptr; } #endregion #region IMAGE_FILE_HEADER /// /// IMAGE_FILE_HEADER. See https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-image_file_header /// [StructLayout(LayoutKind.Explicit)] public struct IMAGE_FILE_HEADER { /// /// Machine /// [FieldOffset(0)] public ushort Machine; /// /// NumberOfSections /// [FieldOffset(2)] public ushort NumberOfSections; /// /// TimeDateStamp /// [FieldOffset(4)] public uint TimeDateStamp; /// /// PointerToSymbolTable /// [FieldOffset(8)] public uint PointerToSymbolTable; /// /// NumberOfSymbols /// [FieldOffset(12)] public uint NumberOfSymbols; /// /// SizeOfOptionalHeader /// [FieldOffset(16)] public ushort SizeOfOptionalHeader; /// /// Characteristics /// [FieldOffset(18)] public ushort Characteristics; } #endregion #region IMAGE_NT_HEADERS /// /// IMAGE_NT_HEADER 32 bit variant. See https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-_image_nt_headers /// [StructLayout(LayoutKind.Explicit)] public struct IMAGE_NT_HEADERS32 { /// /// Signature /// [FieldOffset(0)] public uint Signature; /// /// FileHeader /// [FieldOffset(4)] public IMAGE_FILE_HEADER FileHeader; /// /// OptionalHeader /// [FieldOffset(24)] public IMAGE_OPTIONAL_HEADER32 OptionalHeader; } /// /// IMAGE_NT_HEADER 64 bit variant. See https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-_image_nt_headers /// [StructLayout(LayoutKind.Explicit)] public struct IMAGE_NT_HEADERS64 { /// /// Signature /// [FieldOffset(0)] public uint Signature; /// /// FileHeader /// [FieldOffset(4)] public IMAGE_FILE_HEADER FileHeader; /// /// OptionalHeader /// [FieldOffset(24)] public IMAGE_OPTIONAL_HEADER64 OptionalHeader; } #endregion #region IMAGE_DATA_DIRECTORY /// /// IMAGE_DATA_DIRECTORY. See https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-image_data_directory /// [StructLayout(LayoutKind.Explicit)] public struct IMAGE_DATA_DIRECTORY { /// /// VirtualAddress. /// [FieldOffset(0)] public uint VirtualAddress; /// /// Size. /// [FieldOffset(4)] public uint Size; } #endregion #region IMAGE_OPTIONAL_HEADER32 /// /// IMAGE_OPTIONAL_HEADER 32 bit variant. See https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-_image_optional_header /// [StructLayout(LayoutKind.Explicit)] public struct IMAGE_OPTIONAL_HEADER32 { /// /// Magic /// [FieldOffset(0)] public MagicType Magic; /// /// MajorLinkerVersion /// [FieldOffset(2)] public byte MajorLinkerVersion; /// /// MinorLinkerVersion /// [FieldOffset(3)] public byte MinorLinkerVersion; /// /// SizeOfCode /// [FieldOffset(4)] public uint SizeOfCode; /// /// SizeOfInitializedData /// [FieldOffset(8)] public uint SizeOfInitializedData; /// /// SizeOfUninitializedData /// [FieldOffset(12)] public uint SizeOfUninitializedData; /// /// AddressOfEntryPoint /// [FieldOffset(16)] public uint AddressOfEntryPoint; /// /// BaseOfCode /// [FieldOffset(20)] public uint BaseOfCode; /// /// BaseOfData /// [FieldOffset(24)] public uint BaseOfData; /// /// ImageBase /// [FieldOffset(28)] public uint ImageBase; /// /// SectionAlignment /// [FieldOffset(32)] public uint SectionAlignment; /// /// FileAlignment /// [FieldOffset(36)] public uint FileAlignment; /// /// MajorOperatingSystemVersion /// [FieldOffset(40)] public ushort MajorOperatingSystemVersion; /// /// MinorOperatingSystemVersion /// [FieldOffset(42)] public ushort MinorOperatingSystemVersion; /// /// MajorImageVersion /// [FieldOffset(44)] public ushort MajorImageVersion; /// /// MinorImageVersion /// [FieldOffset(46)] public ushort MinorImageVersion; /// /// MajorSubsystemVersion /// [FieldOffset(48)] public ushort MajorSubsystemVersion; /// /// MinorSubsystemVersion /// [FieldOffset(50)] public ushort MinorSubsystemVersion; /// /// Win32VersionValue /// [FieldOffset(52)] public uint Win32VersionValue; /// /// SizeOfImage /// [FieldOffset(56)] public uint SizeOfImage; /// /// SizeOfHeaders /// [FieldOffset(60)] public uint SizeOfHeaders; /// /// CheckSum /// [FieldOffset(64)] public uint CheckSum; /// /// Subsystem /// [FieldOffset(68)] public SubSystemType Subsystem; /// /// DllCharacteristics /// [FieldOffset(70)] public ushort DllCharacteristics; /// /// SizeOfStackReserve /// [FieldOffset(72)] public uint SizeOfStackReserve; /// /// SizeOfStackCommit /// [FieldOffset(76)] public uint SizeOfStackCommit; /// /// SizeOfHeapReserve /// [FieldOffset(80)] public uint SizeOfHeapReserve; /// /// SizeOfHeapCommit /// [FieldOffset(84)] public uint SizeOfHeapCommit; /// /// LoaderFlags /// [FieldOffset(88)] public uint LoaderFlags; /// /// NumberOfRvaAndSizes /// [FieldOffset(92)] public uint NumberOfRvaAndSizes; /// /// ExportTable /// [FieldOffset(96)] public IMAGE_DATA_DIRECTORY ExportTable; /// /// ImportTable /// [FieldOffset(104)] public IMAGE_DATA_DIRECTORY ImportTable; /// /// ResourceTable /// [FieldOffset(112)] public IMAGE_DATA_DIRECTORY ResourceTable; /// /// ExceptionTable /// [FieldOffset(120)] public IMAGE_DATA_DIRECTORY ExceptionTable; /// /// CertificateTable /// [FieldOffset(128)] public IMAGE_DATA_DIRECTORY CertificateTable; /// /// BaseRelocationTable /// [FieldOffset(136)] public IMAGE_DATA_DIRECTORY BaseRelocationTable; /// /// Debug /// [FieldOffset(144)] public IMAGE_DATA_DIRECTORY Debug; /// /// Architecture /// [FieldOffset(152)] public IMAGE_DATA_DIRECTORY Architecture; /// /// GlobalPtr /// [FieldOffset(160)] public IMAGE_DATA_DIRECTORY GlobalPtr; /// /// TLSTable /// [FieldOffset(168)] public IMAGE_DATA_DIRECTORY TLSTable; /// /// LoadConfigTable /// [FieldOffset(176)] public IMAGE_DATA_DIRECTORY LoadConfigTable; /// /// BoundImport /// [FieldOffset(184)] public IMAGE_DATA_DIRECTORY BoundImport; /// /// IAT /// [FieldOffset(192)] public IMAGE_DATA_DIRECTORY IAT; /// /// DelayImportDescriptor /// [FieldOffset(200)] public IMAGE_DATA_DIRECTORY DelayImportDescriptor; /// /// CLRRuntimeHeader /// [FieldOffset(208)] public IMAGE_DATA_DIRECTORY CLRRuntimeHeader; /// /// Reserved /// [FieldOffset(216)] public IMAGE_DATA_DIRECTORY Reserved; } #endregion #region IMAGE_OPTIONAL_HEADER64 /// /// IMAGE_OPTIONAL_HEADER 64 bit variant. See https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-_image_optional_header /// [StructLayout(LayoutKind.Explicit)] public struct IMAGE_OPTIONAL_HEADER64 { /// /// Magic /// [FieldOffset(0)] public MagicType Magic; /// /// MajorLinkerVersion /// [FieldOffset(2)] public byte MajorLinkerVersion; /// /// MinorLinkerVersion /// [FieldOffset(3)] public byte MinorLinkerVersion; /// /// SizeOfCode /// [FieldOffset(4)] public uint SizeOfCode; /// /// SizeOfInitializedData /// [FieldOffset(8)] public uint SizeOfInitializedData; /// /// SizeOfUninitializedData /// [FieldOffset(12)] public uint SizeOfUninitializedData; /// /// AddressOfEntryPoint /// [FieldOffset(16)] public uint AddressOfEntryPoint; /// /// BaseOfCode /// [FieldOffset(20)] public uint BaseOfCode; /// /// ImageBase /// [FieldOffset(24)] public ulong ImageBase; /// /// SectionAlignment /// [FieldOffset(32)] public uint SectionAlignment; /// /// FileAlignment /// [FieldOffset(36)] public uint FileAlignment; /// /// MajorOperatingSystemVersion /// [FieldOffset(40)] public ushort MajorOperatingSystemVersion; /// /// MinorOperatingSystemVersion /// [FieldOffset(42)] public ushort MinorOperatingSystemVersion; /// /// MajorImageVersion /// [FieldOffset(44)] public ushort MajorImageVersion; /// /// MinorImageVersion /// [FieldOffset(46)] public ushort MinorImageVersion; /// /// MajorSubsystemVersion /// [FieldOffset(48)] public ushort MajorSubsystemVersion; /// /// MinorSubsystemVersion /// [FieldOffset(50)] public ushort MinorSubsystemVersion; /// /// Win32VersionValue /// [FieldOffset(52)] public uint Win32VersionValue; /// /// SizeOfImage /// [FieldOffset(56)] public uint SizeOfImage; /// /// SizeOfHeaders /// [FieldOffset(60)] public uint SizeOfHeaders; /// /// CheckSum /// [FieldOffset(64)] public uint CheckSum; /// /// Subsystem /// [FieldOffset(68)] public SubSystemType Subsystem; /// /// DllCharacteristics /// [FieldOffset(70)] public ushort DllCharacteristics; /// /// SizeOfStackReserve /// [FieldOffset(72)] public ulong SizeOfStackReserve; /// /// SizeOfStackCommit /// [FieldOffset(80)] public ulong SizeOfStackCommit; /// /// SizeOfHeapReserve /// [FieldOffset(88)] public ulong SizeOfHeapReserve; /// /// SizeOfHeapCommit /// [FieldOffset(96)] public ulong SizeOfHeapCommit; /// /// LoaderFlags /// [FieldOffset(104)] public uint LoaderFlags; /// /// NumberOfRvaAndSizes /// [FieldOffset(108)] public uint NumberOfRvaAndSizes; /// /// ExportTable /// [FieldOffset(112)] public IMAGE_DATA_DIRECTORY ExportTable; /// /// ImportTable /// [FieldOffset(120)] public IMAGE_DATA_DIRECTORY ImportTable; /// /// ResourceTable /// [FieldOffset(128)] public IMAGE_DATA_DIRECTORY ResourceTable; /// /// ExceptionTable /// [FieldOffset(136)] public IMAGE_DATA_DIRECTORY ExceptionTable; /// /// CertificateTable /// [FieldOffset(144)] public IMAGE_DATA_DIRECTORY CertificateTable; /// /// BaseRelocationTable /// [FieldOffset(152)] public IMAGE_DATA_DIRECTORY BaseRelocationTable; /// /// Debug /// [FieldOffset(160)] public IMAGE_DATA_DIRECTORY Debug; /// /// Architecture /// [FieldOffset(168)] public IMAGE_DATA_DIRECTORY Architecture; /// /// GlobalPtr /// [FieldOffset(176)] public IMAGE_DATA_DIRECTORY GlobalPtr; /// /// TLSTable /// [FieldOffset(184)] public IMAGE_DATA_DIRECTORY TLSTable; /// /// LoadConfigTable /// [FieldOffset(192)] public IMAGE_DATA_DIRECTORY LoadConfigTable; /// /// BoundImport /// [FieldOffset(200)] public IMAGE_DATA_DIRECTORY BoundImport; /// /// IAT /// [FieldOffset(208)] public IMAGE_DATA_DIRECTORY IAT; /// /// DelayImportDescriptor /// [FieldOffset(216)] public IMAGE_DATA_DIRECTORY DelayImportDescriptor; /// /// CLRRuntimeHeader /// [FieldOffset(224)] public IMAGE_DATA_DIRECTORY CLRRuntimeHeader; /// /// Reserved /// [FieldOffset(232)] public IMAGE_DATA_DIRECTORY Reserved; } #endregion #region MagicType /// /// Image Option Header Magic Type. /// public enum MagicType : ushort { /// /// IMAGE_NT_OPTIONAL_HDR32_MAGIC /// IMAGE_NT_OPTIONAL_HDR32_MAGIC = 0x10b, /// /// IMAGE_NT_OPTIONAL_HDR64_MAGIC /// IMAGE_NT_OPTIONAL_HDR64_MAGIC = 0x20b } #endregion #region SubSystemType /// /// Image Option Header SubSystem Type. /// public enum SubSystemType : ushort { /// /// IMAGE_SUBSYSTEM_UNKNOWN /// IMAGE_SUBSYSTEM_UNKNOWN = 0, /// /// IMAGE_SUBSYSTEM_NATIVE /// IMAGE_SUBSYSTEM_NATIVE = 1, /// /// IMAGE_SUBSYSTEM_WINDOWS_GUI /// IMAGE_SUBSYSTEM_WINDOWS_GUI = 2, /// /// IMAGE_SUBSYSTEM_WINDOWS_CUI /// IMAGE_SUBSYSTEM_WINDOWS_CUI = 3, /// /// IMAGE_SUBSYSTEM_POSIX_CUI /// IMAGE_SUBSYSTEM_POSIX_CUI = 7, /// /// IMAGE_SUBSYSTEM_WINDOWS_CE_GUI /// IMAGE_SUBSYSTEM_WINDOWS_CE_GUI = 9, /// /// IMAGE_SUBSYSTEM_EFI_APPLICATION /// IMAGE_SUBSYSTEM_EFI_APPLICATION = 10, /// /// IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER /// IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER = 11, /// /// IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER /// IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER = 12, /// /// IMAGE_SUBSYSTEM_EFI_ROM /// IMAGE_SUBSYSTEM_EFI_ROM = 13, /// /// IMAGE_SUBSYSTEM_XBOX /// IMAGE_SUBSYSTEM_XBOX = 14 } #endregion #region IMAGE_LOAD_CONFIG_DIRECTORY32 /// /// IMAGE_LOAD_CONFIG_DIRECTORY32. See https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-_image_load_config_directory32 /// [StructLayout(LayoutKind.Sequential)] public struct IMAGE_LOAD_CONFIG_DIRECTORY32 { /// /// Size /// public uint Size; /// /// TimeDateStamp /// public uint TimeDateStamp; /// /// MajorVersio /// public ushort MajorVersion; /// /// MinorVersion /// public ushort MinorVersion; /// /// GlobalFlagsClear /// public uint GlobalFlagsClear; /// /// GlobalFlagsSet /// public uint GlobalFlagsSet; /// /// CriticalSectionDefaultTimeout /// public uint CriticalSectionDefaultTimeout; /// /// DeCommitFreeBlockThreshold /// public uint DeCommitFreeBlockThreshold; /// /// DeCommitTotalFreeThreshold /// public uint DeCommitTotalFreeThreshold; /// /// LockPrefixTable /// public uint LockPrefixTable; /// /// MaximumAllocationSize /// public uint MaximumAllocationSize; /// /// VirtualMemoryThreshold /// public uint VirtualMemoryThreshold; /// /// ProcessHeapFlags /// public uint ProcessHeapFlags; /// /// ProcessAffinityMask /// public uint ProcessAffinityMask; /// /// CSDVersion /// public ushort CSDVersion; /// /// DependentLoadFlags /// public ushort DependentLoadFlags; /// /// EditList /// public uint EditList; /// /// SecurityCookie /// public uint SecurityCookie; /// /// SEHandlerTable /// public uint SEHandlerTable; /// /// SEHandlerCount /// public uint SEHandlerCount; /// /// GuardCFCheckFunctionPointer /// public uint GuardCFCheckFunctionPointer; /// /// GuardCFDispatchFunctionPointer /// public uint GuardCFDispatchFunctionPointer; /// /// GuardCFFunctionTable /// public uint GuardCFFunctionTable; /// /// GuardCFFunctionCount /// public uint GuardCFFunctionCount; /// /// GuardFlags /// public uint GuardFlags; /// /// CodeIntegrity /// public IMAGE_LOAD_CONFIG_CODE_INTEGRITY CodeIntegrity; /// /// GuardAddressTakenIatEntryTable /// public uint GuardAddressTakenIatEntryTable; /// /// GuardAddressTakenIatEntryCount /// public uint GuardAddressTakenIatEntryCount; /// /// GuardLongJumpTargetTable /// public uint GuardLongJumpTargetTable; /// /// GuardLongJumpTargetCount /// public uint GuardLongJumpTargetCount; /// /// DynamicValueRelocTable /// public uint DynamicValueRelocTable; /// /// CHPEMetadataPointer /// public uint CHPEMetadataPointer; /// /// GuardRFFailureRoutine /// public uint GuardRFFailureRoutine; /// /// GuardRFFailureRoutineFunctionPointer /// public uint GuardRFFailureRoutineFunctionPointer; /// /// DynamicValueRelocTableOffset /// public uint DynamicValueRelocTableOffset; /// /// DynamicValueRelocTableSection /// public ushort DynamicValueRelocTableSection; /// /// Reserved2 /// public ushort Reserved2; /// /// GuardRFVerifyStackPointerFunctionPointer /// public uint GuardRFVerifyStackPointerFunctionPointer; /// /// HotPatchTableOffset /// public uint HotPatchTableOffset; /// /// Reserved3 /// public uint Reserved3; /// /// EnclaveConfigurationPointer /// public uint EnclaveConfigurationPointer; /// /// VolatileMetadataPointer /// public uint VolatileMetadataPointer; } #endregion #region IMAGE_LOAD_CONFIG_DIRECTORY64 /// /// IMAGE_LOAD_CONFIG_DIRECTORY32. See https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-_image_load_config_directory64 /// [StructLayout(LayoutKind.Sequential)] public struct IMAGE_LOAD_CONFIG_DIRECTORY64 { /// /// Size /// public uint Size; /// /// TimeDateStamp /// public uint TimeDateStamp; /// /// MajorVersion /// public ushort MajorVersion; /// /// MinorVersion /// public ushort MinorVersion; /// /// GlobalFlagsClear /// public uint GlobalFlagsClear; /// /// GlobalFlagsSet /// public uint GlobalFlagsSet; /// /// CriticalSectionDefaultTimeout /// public uint CriticalSectionDefaultTimeout; /// /// DeCommitFreeBlockThreshold /// public ulong DeCommitFreeBlockThreshold; /// /// DeCommitTotalFreeThreshold /// public ulong DeCommitTotalFreeThreshold; /// /// LockPrefixTable /// public ulong LockPrefixTable; /// /// MaximumAllocationSize /// public ulong MaximumAllocationSize; /// /// VirtualMemoryThreshold /// public ulong VirtualMemoryThreshold; /// /// ProcessAffinityMask /// public ulong ProcessAffinityMask; /// /// ProcessHeapFlags /// public uint ProcessHeapFlags; /// /// CSDVersion /// public ushort CSDVersion; /// /// DependentLoadFlags /// public ushort DependentLoadFlags; /// /// EditList /// public ulong EditList; /// /// SecurityCookie /// public ulong SecurityCookie; /// /// SEHandlerTable /// public ulong SEHandlerTable; /// /// SEHandlerCount /// public ulong SEHandlerCount; /// /// GuardCFCheckFunctionPointer /// public ulong GuardCFCheckFunctionPointer; /// /// GuardCFDispatchFunctionPointer /// public ulong GuardCFDispatchFunctionPointer; /// /// GuardCFFunctionTable /// public ulong GuardCFFunctionTable; /// /// GuardCFFunctionCount /// public ulong GuardCFFunctionCount; /// /// GuardFlags /// public uint GuardFlags; /// /// CodeIntegrity /// public IMAGE_LOAD_CONFIG_CODE_INTEGRITY CodeIntegrity; /// /// GuardAddressTakenIatEntryTable /// public ulong GuardAddressTakenIatEntryTable; /// /// GuardAddressTakenIatEntryCount /// public ulong GuardAddressTakenIatEntryCount; /// /// GuardLongJumpTargetTable /// public ulong GuardLongJumpTargetTable; /// /// GuardLongJumpTargetCount /// public ulong GuardLongJumpTargetCount; /// /// DynamicValueRelocTable /// public ulong DynamicValueRelocTable; /// /// CHPEMetadataPointer /// public ulong CHPEMetadataPointer; /// /// GuardRFFailureRoutine /// public ulong GuardRFFailureRoutine; /// /// GuardRFFailureRoutineFunctionPointer /// public ulong GuardRFFailureRoutineFunctionPointer; /// /// DynamicValueRelocTableOffset /// public uint DynamicValueRelocTableOffset; /// /// DynamicValueRelocTableSection /// public ushort DynamicValueRelocTableSection; /// /// Reserved2 /// public ushort Reserved2; /// /// GuardRFVerifyStackPointerFunctionPointer /// public ulong GuardRFVerifyStackPointerFunctionPointer; /// /// HotPatchTableOffset /// public uint HotPatchTableOffset; /// /// Reserved3 /// public uint Reserved3; /// /// EnclaveConfigurationPointer /// public ulong EnclaveConfigurationPointer; /// /// VolatileMetadataPointer /// public ulong VolatileMetadataPointer; } #endregion #region IMAGE_LOAD_CONFIG_CODE_INTEGRITY /// /// IMAGE_LOAD_CONFIG_CODE_INTEGRITY. /// [StructLayout(LayoutKind.Sequential)] public struct IMAGE_LOAD_CONFIG_CODE_INTEGRITY { /// /// Flags /// public ushort Flags; /// /// Catalog /// public ushort Catalog; /// /// CatalogOffset /// public uint CatalogOffset; /// /// Reserved /// public uint Reserved; }; #endregion #region LOADED_IMAGE /// /// LOADED_IMAGE. See https://docs.microsoft.com/en-us/windows/win32/api/dbghelp/ns-dbghelp-_loaded_image /// public struct LOADED_IMAGE { /// /// ModuleName /// public IntPtr ModuleName; /// /// hFile /// public IntPtr hFile; /// /// MappedAddress /// public IntPtr MappedAddress; /// /// FileHeader /// public IntPtr FileHeader; /// /// LastRvaSection /// public IntPtr LastRvaSection; /// /// NumberOfSections /// public uint NumberOfSections; /// /// Sections /// public IntPtr Sections; /// /// Characteristics /// public uint Characteristics; /// /// fSystemImage /// public bool fSystemImage; /// /// fDOSImage /// public bool fDOSImage; /// /// fReadOnly /// public bool fReadOnly; /// /// Version /// public byte Version; /// /// Links /// public LIST_ENTRY Links; /// /// SizeOfImage /// public uint SizeOfImage; } #endregion #region List_Entry /// /// Describes an entry in a doubly linked list or serves as the header for such a list. See https://docs.microsoft.com/en-us/windows/win32/api/ntdef/ns-ntdef-_list_entry /// public struct LIST_ENTRY { /// /// Flink points to the next entry in the list. /// public IntPtr Flink; /// /// Blink points to the previous entry in the list. /// public IntPtr Blink; } #endregion #endregion #region Process Memory Information #region AllocationProtect /// /// AllocationProtect. /// public enum AllocationProtect : uint { /// /// PAGE_EXECUTE /// PAGE_EXECUTE = 0x00000010, /// /// PAGE_EXECUTE_READ /// PAGE_EXECUTE_READ = 0x00000020, /// /// PAGE_EXECUTE_READWRITE /// PAGE_EXECUTE_READWRITE = 0x00000040, /// /// PAGE_EXECUTE_WRITECOPY /// PAGE_EXECUTE_WRITECOPY = 0x00000080, /// /// PAGE_NOACCESS /// PAGE_NOACCESS = 0x00000001, /// /// PAGE_READONLY /// PAGE_READONLY = 0x00000002, /// /// PAGE_READWRITE /// PAGE_READWRITE = 0x00000004, /// /// PAGE_WRITECOPY /// PAGE_WRITECOPY = 0x00000008, /// /// PAGE_GUARD /// PAGE_GUARD = 0x00000100, /// /// PAGE_NOCACHE /// PAGE_NOCACHE = 0x00000200, /// /// PAGE_WRITECOMBINE /// PAGE_WRITECOMBINE = 0x00000400 } #endregion #region StateEnum /// /// StateEnum /// public enum StateEnum : uint { /// /// MEM_COMMIT /// MEM_COMMIT = 0x1000, /// /// MEM_FREE /// MEM_FREE = 0x10000, /// /// MEM_RESERVE /// MEM_RESERVE = 0x2000 } #endregion #region TypeEnum /// /// TypeEnum /// public enum TypeEnum : uint { /// /// MEM_IMAGE /// MEM_IMAGE = 0x1000000, /// /// MEM_MAPPED /// MEM_MAPPED = 0x40000, /// /// MEM_PRIVATE /// MEM_PRIVATE = 0x20000 } #endregion #region MEMORY_BASIC_INFORMATION32 /// /// MEMORY_BASIC_INFORMATION32. See https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-_memory_basic_information /// [StructLayout(LayoutKind.Sequential)] public struct MEMORY_BASIC_INFORMATION32 { /// /// BaseAddress /// public IntPtr BaseAddress; /// /// AllocationBase /// public IntPtr AllocationBase; /// /// AllocationProtec /// public uint AllocationProtect; /// /// RegionSize /// public IntPtr RegionSize; /// /// State /// public StateEnum State; /// /// Protect /// public uint Protect; /// /// Type /// public TypeEnum Type; } #endregion #region MEMORY_BASIC_INFORMATION64 /// /// MEMORY_BASIC_INFORMATION32. See https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-_memory_basic_information /// [StructLayout(LayoutKind.Sequential)] public struct MEMORY_BASIC_INFORMATION64 { /// /// BaseAddress /// public ulong BaseAddress; /// /// AllocationBase /// public ulong AllocationBase; /// /// AllocationProtect /// public uint AllocationProtect; /// /// __alignment1 /// public int __alignment1; /// /// RegionSize /// public ulong RegionSize; /// /// State /// public StateEnum State; /// /// Protect /// public int Protect; /// /// Type /// public TypeEnum Type; /// /// __alignment2 /// public int __alignment2; } #endregion #region ProcessAccessFlags /// /// ProcessAccessFlags /// [Flags] public enum ProcessAccessFlags : uint { /// /// All /// All = 0x001F0FFF, /// /// Terminate /// Terminate = 0x00000001, /// /// CreateThread /// CreateThread = 0x00000002, /// /// VirtualMemoryOperation /// VirtualMemoryOperation = 0x00000008, /// /// VirtualMemoryRead /// VirtualMemoryRead = 0x00000010, /// /// VirtualMemoryWrite /// VirtualMemoryWrite = 0x00000020, /// /// DuplicateHandle /// DuplicateHandle = 0x00000040, /// /// CreateProcess /// CreateProcess = 0x000000080, /// /// SetQuota /// SetQuota = 0x00000100, /// /// SetInformation /// SetInformation = 0x00000200, /// /// QueryInformation /// QueryInformation = 0x00000400, /// /// QueryLimitedInformation /// QueryLimitedInformation = 0x00001000, /// /// Synchronize /// Synchronize = 0x00100000 } #endregion #region LoadLibraryFlags /// /// LoadLibraryFlags /// [Flags] public enum LoadLibraryFlags : uint { /// /// None /// None = 0, /// /// DONT_RESOLVE_DLL_REFERENCES /// DONT_RESOLVE_DLL_REFERENCES = 0x00000001, /// /// LOAD_IGNORE_CODE_AUTHZ_LEVEL /// LOAD_IGNORE_CODE_AUTHZ_LEVEL = 0x00000010, /// /// LOAD_LIBRARY_AS_DATAFILE /// LOAD_LIBRARY_AS_DATAFILE = 0x00000002, /// /// LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE /// LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE = 0x00000040, /// /// LOAD_LIBRARY_AS_IMAGE_RESOURCE /// LOAD_LIBRARY_AS_IMAGE_RESOURCE = 0x00000020, /// /// LOAD_LIBRARY_SEARCH_APPLICATION_DIR /// LOAD_LIBRARY_SEARCH_APPLICATION_DIR = 0x00000200, /// /// LOAD_LIBRARY_SEARCH_DEFAULT_DIRS /// LOAD_LIBRARY_SEARCH_DEFAULT_DIRS = 0x00001000, /// /// LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR /// LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR = 0x00000100, /// /// LOAD_LIBRARY_SEARCH_SYSTEM32 /// LOAD_LIBRARY_SEARCH_SYSTEM32 = 0x00000800, /// /// LOAD_LIBRARY_SEARCH_USER_DIRS /// LOAD_LIBRARY_SEARCH_USER_DIRS = 0x00000400, /// /// LOAD_WITH_ALTERED_SEARCH_PATH /// LOAD_WITH_ALTERED_SEARCH_PATH = 0x00000008 } #endregion #endregion #region Thread Context #region ThreadAccess /// /// Enum to specify access level required when accessing a thread. /// [Flags] public enum ThreadAccess : int { /// /// TERMINATE /// TERMINATE = (0x0001), /// /// SUSPEND_RESUME /// SUSPEND_RESUME = (0x0002), /// /// GET_CONTEXT /// GET_CONTEXT = (0x0008), /// /// SET_CONTEXT /// SET_CONTEXT = (0x0010), /// /// SET_INFORMATION /// SET_INFORMATION = (0x0020), /// /// QUERY_INFORMATION /// QUERY_INFORMATION = (0x0040), /// /// SET_THREAD_TOKEN /// SET_THREAD_TOKEN = (0x0080), /// /// IMPERSONATE /// IMPERSONATE = (0x0100), /// /// DIRECT_IMPERSONATION /// DIRECT_IMPERSONATION = (0x0200), /// /// All_ACCESS /// All_ACCESS = (0xFFFF) } #endregion #region CONTEXT_FLAGS /// /// CONTEXT_FLAGS /// public enum CONTEXT_FLAGS : uint { /// /// CONTEXT_i386 /// CONTEXT_i386 = 0x10000, /// /// CONTEXT_i486 /// CONTEXT_i486 = 0x10000, /// /// CONTEXT_CONTROL /// CONTEXT_CONTROL = CONTEXT_i386 | 0x01, /// /// CONTEXT_INTEGER /// CONTEXT_INTEGER = CONTEXT_i386 | 0x02, /// /// CONTEXT_SEGMENTS /// CONTEXT_SEGMENTS = CONTEXT_i386 | 0x04, /// /// CONTEXT_FLOATING_POINT /// CONTEXT_FLOATING_POINT = CONTEXT_i386 | 0x08, /// /// CONTEXT_DEBUG_REGISTERS /// CONTEXT_DEBUG_REGISTERS = CONTEXT_i386 | 0x10, /// /// CONTEXT_EXTENDED_REGISTERS /// CONTEXT_EXTENDED_REGISTERS = CONTEXT_i386 | 0x20, /// /// CONTEXT_FULL /// CONTEXT_FULL = CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS, /// /// CONTEXT_ALL /// CONTEXT_ALL = CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS | CONTEXT_FLOATING_POINT | CONTEXT_DEBUG_REGISTERS | CONTEXT_EXTENDED_REGISTERS } #endregion #region FLOATING_SAVE_AREA /// /// x86 Save area data. See https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-_wow64_floating_save_area /// [StructLayout(LayoutKind.Sequential)] public struct FLOATING_SAVE_AREA { /// /// ControlWord /// public uint ControlWord; /// /// StatusWord /// public uint StatusWord; /// /// TagWord /// public uint TagWord; /// /// ErrorOffset /// public uint ErrorOffset; /// /// ErrorSelector /// public uint ErrorSelector; /// /// DataOffset /// public uint DataOffset; /// /// DataSelector /// public uint DataSelector; /// /// RegisterArea /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 80)] public byte[] RegisterArea; /// /// Cr0NpxState /// public uint Cr0NpxState; } #endregion #region CONTEXT32 /// /// Structure for holding x86 register values. /// [StructLayout(LayoutKind.Sequential)] public struct CONTEXT32 { /// /// ContextFlags /// public CONTEXT_FLAGS ContextFlags; /// /// Dr0 /// public uint Dr0; /// /// Dr1 /// public uint Dr1; /// /// Dr2 /// public uint Dr2; /// /// Dr3 /// public uint Dr3; /// /// Dr6 /// public uint Dr6; /// /// Dr7 /// public uint Dr7; /// /// FloatSave /// public FLOATING_SAVE_AREA FloatSave; /// /// SegGs /// public uint SegGs; /// /// SegFs /// public uint SegFs; /// /// SegEs /// public uint SegEs; /// /// SegDs /// public uint SegDs; /// /// Edi /// public uint Edi; /// /// Esi /// public uint Esi; /// /// Ebx /// public uint Ebx; /// /// Edx /// public uint Edx; /// /// Ecx /// public uint Ecx; /// /// Eax /// public uint Eax; /// /// Ebp /// public uint Ebp; /// /// Eip /// public uint Eip; /// /// SegCs /// public uint SegCs; /// /// EFlags /// public uint EFlags; /// /// Esp /// public uint Esp; /// /// SegSs /// public uint SegSs; /// /// ExtendedRegisters /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 512)] public byte[] ExtendedRegisters; /// /// Overridden ToString method, returns register values for the current thread. /// /// String public override string ToString() { string ret = ""; ret += "EDI = " + Edi.ToString("X8") + Environment.NewLine; ret += "ESI = " + Esi.ToString("X8") + Environment.NewLine; ret += "EBX = " + Ebx.ToString("X8") + Environment.NewLine; ret += "EDX = " + Edx.ToString("X8") + Environment.NewLine; ret += "ECX = " + Ecx.ToString("X8") + Environment.NewLine; ret += "EAX = " + Eax.ToString("X8") + Environment.NewLine; ret += "EBP = " + Ebp.ToString("X8") + Environment.NewLine; ret += "ESP = " + Esp.ToString("X8") + Environment.NewLine; ret += "EIP = " + Eip.ToString("X8") + Environment.NewLine; return ret; } } #endregion #region M128A /// /// M128A /// [StructLayout(LayoutKind.Sequential)] public struct M128A { /// /// High /// public ulong High; /// /// Low /// public long Low; /// /// ToString Override /// /// Returns a String public override string ToString() { return string.Format("High:{0}, Low:{1}", this.High, this.Low); } } #endregion #region XSAVE_FORMAT64 /// /// x64 Save area data. /// [StructLayout(LayoutKind.Sequential, Pack = 16)] public struct XSAVE_FORMAT64 { /// /// ControlWord /// public ushort ControlWord; /// /// StatusWord /// public ushort StatusWord; /// /// TagWord /// public byte TagWord; /// /// Reserved1 /// public byte Reserved1; /// /// ErrorOpcode /// public ushort ErrorOpcode; /// /// ErrorOffset /// public uint ErrorOffset; /// /// ErrorSelector /// public ushort ErrorSelector; /// /// Reserved2 /// public ushort Reserved2; /// /// DataOffset /// public uint DataOffset; /// /// DataSelector /// public ushort DataSelector; /// /// Reserved3 /// public ushort Reserved3; /// /// MxCsr /// public uint MxCsr; /// /// MxCsr_Mask /// public uint MxCsr_Mask; /// /// FloatRegisters /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public M128A[] FloatRegisters; /// /// XmmRegisters /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public M128A[] XmmRegisters; /// /// Reserved4 /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 96)] public byte[] Reserved4; } #endregion #region CONTEXT64 /// /// Structure for holding x64 register values. /// [StructLayout(LayoutKind.Sequential, Pack = 16)] public struct CONTEXT64 { /// /// P1Home /// public ulong P1Home; /// /// P2Home /// public ulong P2Home; /// /// P3Home /// public ulong P3Home; /// /// P4Home /// public ulong P4Home; /// /// P5Home /// public ulong P5Home; /// /// P6Home /// public ulong P6Home; /// /// ContextFlags /// public CONTEXT_FLAGS ContextFlags; /// /// MxCsr /// public uint MxCsr; /// /// SegCs /// public ushort SegCs; /// /// SegDs /// public ushort SegDs; /// /// SegEs /// public ushort SegEs; /// /// SegFs /// public ushort SegFs; /// /// SegGs /// public ushort SegGs; /// /// SegSs /// public ushort SegSs; /// /// EFlags /// public uint EFlags; /// /// Dr0 /// public ulong Dr0; /// /// Dr1 /// public ulong Dr1; /// /// Dr2 /// public ulong Dr2; /// /// Dr3 /// public ulong Dr3; /// /// Dr6 /// public ulong Dr6; /// /// Dr7 /// public ulong Dr7; /// /// Rax /// public ulong Rax; /// /// Rcx /// public ulong Rcx; /// /// Rdx /// public ulong Rdx; /// /// Rbx /// public ulong Rbx; /// /// Rsp /// public ulong Rsp; /// /// Rbp /// public ulong Rbp; /// /// Rsi /// public ulong Rsi; /// /// Rdi /// public ulong Rdi; /// /// R8 /// public ulong R8; /// /// R9 /// public ulong R9; /// /// R10 /// public ulong R10; /// /// R11 /// public ulong R11; /// /// R12 /// public ulong R12; /// /// R13 /// public ulong R13; /// /// R14 /// public ulong R14; /// /// R15 /// public ulong R15; /// /// Rip /// public ulong Rip; /// /// DUMMYUNIONNAME /// public XSAVE_FORMAT64 DUMMYUNIONNAME; /// /// VectorRegister /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = 26)] public M128A[] VectorRegister; /// /// VectorControl /// public ulong VectorControl; /// /// DebugControl /// public ulong DebugControl; /// /// LastBranchToRip /// public ulong LastBranchToRip; /// /// LastBranchFromRip /// public ulong LastBranchFromRip; /// /// LastExceptionToRip /// public ulong LastExceptionToRip; /// /// LastExceptionFromRip /// public ulong LastExceptionFromRip; /// /// Overridden ToString method, returns register values for the current thread. /// /// String public override string ToString() { string ret = ""; ret += "RAX = " + Rax.ToString("X16") + Environment.NewLine; ret += "RCX = " + Rcx.ToString("X16") + Environment.NewLine; ret += "RDX = " + Rdx.ToString("X16") + Environment.NewLine; ret += "RBX = " + Rbx.ToString("X16") + Environment.NewLine; ret += "RSP = " + Rsp.ToString("X16") + Environment.NewLine; ret += "RBP = " + Rbp.ToString("X16") + Environment.NewLine; ret += "RSI = " + Rsi.ToString("X16") + Environment.NewLine; ret += "RDI = " + Rdi.ToString("X16") + Environment.NewLine; ret += "R08 = " + R8.ToString("X16") + Environment.NewLine; ret += "R09 = " + R9.ToString("X16") + Environment.NewLine; ret += "R10 = " + R10.ToString("X16") + Environment.NewLine; ret += "R11 = " + R11.ToString("X16") + Environment.NewLine; ret += "R12 = " + R12.ToString("X16") + Environment.NewLine; ret += "R13 = " + R13.ToString("X16") + Environment.NewLine; ret += "R14 = " + R14.ToString("X16") + Environment.NewLine; ret += "R15 = " + R15.ToString("X16") + Environment.NewLine; ret += "RIP = " + Rip.ToString("X16") + Environment.NewLine; return ret; } } #endregion #region RegisterInfo /// /// Register information /// public class RegisterInfo { /// /// Register name. /// public string Register { get; set; } /// /// Register value. /// public IntPtr RegisterValue { get; set; } /// /// Register Offset. /// public int RegisterOffset { get; set; } /// /// String offset. /// public int StringOffset { get; set; } /// /// Buffer size. /// public int BufferSize { get; set; } /// /// Thread ID. /// public int ThreadID { get; set; } /// /// Overwritten. /// public bool overwritten { get; set; } } #endregion #endregion #region TEB /// /// ThreadBasicInformation /// [StructLayout(LayoutKind.Sequential)] public struct ThreadBasicInformation { /// /// ExitStatus /// public uint ExitStatus; /// /// TebBaseAdress /// public IntPtr TebBaseAdress; /// /// Identifiers /// public ClientID Identifiers; /// /// AffinityMask /// public uint AffinityMask; /// /// Priority /// public uint Priority; /// /// BasePriority /// public uint BasePriority; } /// /// ClientID /// [StructLayout(LayoutKind.Sequential)] public struct ClientID { /// /// ProcessID /// public IntPtr ProcessId; /// /// ThreadID /// public IntPtr ThreadId; } /// /// Thread Environment Block. /// [StructLayout(LayoutKind.Sequential)] public struct TEB { /// /// CurrentSehFrame /// public IntPtr CurrentSehFrame; /// /// TopOfStack /// public IntPtr TopOfStack; /// /// BottomOfStack /// public IntPtr BottomOfStack; /// /// SubSystemTeb /// public IntPtr SubSystemTeb; /// /// FiberData /// public IntPtr FiberData; /// /// ArbitraryDataSlot /// public IntPtr ArbitraryDataSlot; /// /// Teb /// public IntPtr Teb; /// /// EnvironmentPointer /// public IntPtr EnvironmentPointer; /// /// Identifiers /// public ClientID Identifiers; /// /// RpcHandle /// public IntPtr RpcHandle; /// /// Tls /// public IntPtr Tls; /// /// Peb /// public IntPtr Peb; /// /// LastErrorNumber /// public int LastErrorNumber; /// /// CriticalSectionsCount /// public int CriticalSectionsCount; /// /// CsrClientThread /// public IntPtr CsrClientThread; /// /// Win32ThreadInfo /// public IntPtr Win32ThreadInfo; /// /// Win32ClientInfo /// public byte[] Win32ClientInfo; /// /// WoW64Reserved /// public IntPtr WoW64Reserved; /// /// CurrentLocale /// public IntPtr CurrentLocale; /// /// FpSoftwareStatusRegister /// public IntPtr FpSoftwareStatusRegister; /// /// SystemReserved1 /// public byte[] SystemReserved1; /// /// ExceptionCode /// public IntPtr ExceptionCode; /// /// ActivationContextStack /// public byte[] ActivationContextStack; /// /// SpareBytes /// public byte[] SpareBytes; /// /// SystemReserved2 /// public byte[] SystemReserved2; /// /// GdiTebBatch /// public byte[] GdiTebBatch; /// /// GdiRegion /// public IntPtr GdiRegion; /// /// GdiPen /// public IntPtr GdiPen; /// /// GdiBrush /// public IntPtr GdiBrush; /// /// RealProcessId /// public int RealProcessId; /// /// RealThreadId /// public int RealThreadId; /// /// GdiCachedProcessHandle /// public IntPtr GdiCachedProcessHandle; /// /// GdiClientProcessId /// public IntPtr GdiClientProcessId; /// /// GdiClientThreadId /// public IntPtr GdiClientThreadId; /// /// GdiThreadLocalInfo /// public IntPtr GdiThreadLocalInfo; /// /// UserReserved1 /// public byte[] UserReserved1; /// /// GlReserved1 /// public byte[] GlReserved1; /// /// LastStatusValue /// public int LastStatusValue; /// /// StaticUnicodeString /// public byte[] StaticUnicodeString; /// /// DeallocationStack /// public IntPtr DeallocationStack; /// /// TlsSlots /// public byte[] TlsSlots; /// /// TlsLinks /// public long TlsLinks; /// /// Vdm /// public IntPtr Vdm; /// /// RpcReserved /// public IntPtr RpcReserved; /// /// ThreadErrorMode /// public IntPtr ThreadErrorMode; } #endregion #region ToolHelp /// /// ToolHelp SnapshotFlags /// [Flags] public enum SnapshotFlags : uint { HeapList = 0x00000001, Process = 0x00000002, Thread = 0x00000004, Module = 0x00000008, Module32 = 0x00000010, Inherit = 0x80000000, All = 0x0000001F, NoHeaps = 0x40000000 } /// /// ToolHelp PROCESSENTRY32 /// [StructLayout(LayoutKind.Sequential)] public struct PROCESSENTRY32 { const int MAX_PATH = 260; internal uint dwSize; internal uint cntUsage; internal uint th32ProcessID; internal IntPtr th32DefaultHeapID; internal uint th32ModuleID; internal uint cntThreads; internal uint th32ParentProcessID; internal int pcPriClassBase; internal uint dwFlags; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH)] internal string szExeFile; } /// /// Describes one entry (block) of a heap that is being examined. /// [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] public struct HEAPLIST32 { internal IntPtr dwSize; internal uint th32ProcessID; internal IntPtr th32HeapID; internal uint dwFlags; } /// /// Describes one entry (block) of a heap that is being examined. /// [StructLayout(LayoutKind.Sequential)] public struct HEAPENTRY32 { /** The size of the structure, in bytes **/ internal IntPtr dwSize; /** A handle to the heap block **/ internal IntPtr hHandle; /** The linear address of the start of the block **/ internal IntPtr dwAddress; /** The size of the heap block, in bytes **/ internal IntPtr dwBlockSize; /** This member can be one of the following values. LF32_FIXED 0x00000001 LF32_FREE 0x00000002 LF32_MOVEABLE 0x00000004 **/ internal uint dwFlags; /** This member is no longer used and is always set to zero. **/ internal uint dwLockCount; /** Reserved; do not use or alter **/ internal uint dwResvd; /** The identifier of the process that uses the heap **/ internal uint th32ProcessID; /** The heap identifier. This is not a handle, and has meaning only to the tool help functions **/ internal IntPtr th32HeapID; } #endregion } #endregion } ================================================ FILE: ERC/ERC/FodyWeavers.xml ================================================  ================================================ FILE: ERC/ERC/FodyWeavers.xsd ================================================  A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with line breaks A list of assembly names to include from the default action of "embed all Copy Local references", delimited with line breaks. A list of runtime assembly names to exclude from the default action of "embed all Copy Local references", delimited with line breaks A list of runtime assembly names to include from the default action of "embed all Copy Local references", delimited with line breaks. A list of unmanaged 32 bit assembly names to include, delimited with line breaks. A list of unmanaged 64 bit assembly names to include, delimited with line breaks. The order of preloaded assemblies, delimited with line breaks. This will copy embedded files to disk before loading them into memory. This is helpful for some scenarios that expected an assembly to be loaded from a physical file. Controls if .pdbs for reference assemblies are also embedded. Controls if runtime assemblies are also embedded. Controls whether the runtime assemblies are embedded with their full path or only with their assembly name. Embedded assemblies are compressed by default, and uncompressed when they are loaded. You can turn compression off with this option. As part of Costura, embedded assemblies are no longer included as part of the build. This cleanup can be turned off. Costura by default will load as part of the module initialization. This flag disables that behavior. Make sure you call CosturaUtility.Initialize() somewhere in your code. Costura will by default use assemblies with a name like 'resources.dll' as a satellite resource and prepend the output path. This flag disables that behavior. A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with | A list of assembly names to include from the default action of "embed all Copy Local references", delimited with |. A list of runtime assembly names to exclude from the default action of "embed all Copy Local references", delimited with | A list of runtime assembly names to include from the default action of "embed all Copy Local references", delimited with |. A list of unmanaged 32 bit assembly names to include, delimited with |. A list of unmanaged 64 bit assembly names to include, delimited with |. The order of preloaded assemblies, delimited with |. 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. A comma-separated list of error codes that can be safely ignored in assembly verification. 'false' to turn off automatic generation of the XML Schema file. ================================================ FILE: ERC/ERC/Heap_Info.cs ================================================ using System; using System.Collections.Generic; using System.Runtime.InteropServices; using ERC.Structures; namespace ERC { public class HeapInfo { #region Variables internal List HeapEntries = new List(); internal List HeapLists = new List(); internal ProcessInfo HeapProcess; #endregion #region Constructor public HeapInfo(ProcessInfo info) { HeapProcess = info; HEAPLIST32 firstHeapList = new HEAPLIST32(); firstHeapList.dwSize = (IntPtr)Marshal.SizeOf(typeof(HEAPLIST32)); IntPtr Handle = ErcCore.CreateToolhelp32Snapshot(SnapshotFlags.HeapList, (uint)info.ProcessID); if ((int)Handle == -1) { throw new ERCException("CreateToolhelp32Snapshot returned an invalid handle value (-1)"); } if (ErcCore.Heap32ListFirst(Handle, ref firstHeapList)) { HeapLists.Add(firstHeapList); bool moreHeaps = false; do { HEAPLIST32 currentHeap = new HEAPLIST32(); currentHeap.dwSize = (IntPtr)Marshal.SizeOf(typeof(HEAPLIST32)); moreHeaps = ErcCore.Heap32ListNext(Handle, ref currentHeap); if(HeapEntries.Count == 0) { currentHeap = firstHeapList; } if (moreHeaps) { HeapLists.Add(currentHeap); HEAPENTRY32 heapentry32 = new HEAPENTRY32(); heapentry32.dwSize = (IntPtr)Marshal.SizeOf(typeof(HEAPENTRY32)); if (ErcCore.Heap32First(ref heapentry32, (uint)HeapProcess.ProcessID, currentHeap.th32HeapID)) { bool moreheapblocks = false; do { HeapEntries.Add(heapentry32); moreheapblocks = ErcCore.Heap32Next(ref heapentry32); } while (moreheapblocks); } } } while (moreHeaps); } else { throw new ERCException("Heap32ListFirst returned an invalid response. Error: " + Utilities.Win32Errors.GetLastWin32Error()); } } #endregion #region Accessors /// /// Searches heap entries for a specified pattern. Returns pointers to all instances of the pattern. If heapID and startAddress are both supplied heapID takes precedence. /// /// byte array containing the pattern to search for /// ID of the heap to be searched(Optional) /// Start address of the heap entry to be searched in hexadecimal(Optional) /// Returns an ERCResult of IntPtr containing pointers to all instances of the pattern found. public ErcResult>> SearchHeap(byte[] searchBytes, ulong heapID = 0, string hexStartAddress = "") { ErcResult>> result = new ErcResult>>(HeapProcess); result.ReturnValue = new List>(); if (hexStartAddress.Contains("0x") || hexStartAddress.Contains("0x") || hexStartAddress.Contains("x") || hexStartAddress.Contains("X")) { hexStartAddress = hexStartAddress.Replace("0x", ""); hexStartAddress = hexStartAddress.Replace("0X", ""); hexStartAddress = hexStartAddress.Replace("X", ""); hexStartAddress = hexStartAddress.Replace("x", ""); } IntPtr startAddress = IntPtr.Zero; IntPtr HeapID = IntPtr.Zero; if (heapID != 0) { HeapID = (IntPtr)heapID; } if (HeapProcess.ProcessMachineType == MachineType.I386) { try { startAddress = (IntPtr)Convert.ToInt32(hexStartAddress, 16); } catch { } } else { try { startAddress = (IntPtr)Convert.ToInt64(hexStartAddress, 16); } catch { } } if (searchBytes.Length < 3) { result.Error = new ERCException("Search pattern not long enough. Minimum length is 3 bytes"); result.ReturnValue = null; return result; } if(heapID != 0) { foreach (HEAPENTRY32 he in HeapEntries) { if(he.th32HeapID == HeapID) { byte[] bytes = HeapProcess.DumpMemoryRegion(he.dwAddress, (int)he.dwBlockSize).ReturnValue; int maxFirstCharSlot = bytes.Length - searchBytes.Length + 1; for (int i = 0; i < maxFirstCharSlot; i++) { if (bytes[i] != searchBytes[0]) continue; for (int j = searchBytes.Length - 1; j >= 1; j--) { if (bytes[i + j] != searchBytes[j]) break; if (j == 1) { Tuple element = new Tuple(he.dwAddress + i, he.th32HeapID, he.dwAddress); result.ReturnValue.Add(element); } } } } } } else if(startAddress != IntPtr.Zero) { foreach (HEAPENTRY32 he in HeapEntries) { if (he.dwAddress == startAddress) { byte[] bytes = HeapProcess.DumpMemoryRegion((IntPtr)startAddress, (int)he.dwBlockSize).ReturnValue; int maxFirstCharSlot = bytes.Length - searchBytes.Length + 1; for (int i = 0; i < maxFirstCharSlot; i++) { if (bytes[i] != searchBytes[0]) { continue; } for (int j = searchBytes.Length - 1; j >= 1; j--) { if (bytes[i + j] != searchBytes[j]) { break; } if (j == 1) { Tuple element = new Tuple(he.dwAddress + i, he.th32HeapID, he.dwAddress); result.ReturnValue.Add(element); } } } } } } else { foreach(HEAPENTRY32 he in HeapEntries) { byte[] bytes = HeapProcess.DumpMemoryRegion(he.dwAddress, (int)he.dwBlockSize).ReturnValue; int maxFirstCharSlot = bytes.Length - searchBytes.Length + 1; for (int i = 0; i < maxFirstCharSlot; i++) { if (bytes[i] != searchBytes[0]) continue; for (int j = searchBytes.Length - 1; j >= 1; j--) { if (bytes[i + j] != searchBytes[j]) break; if (j == 1) { Tuple element = new Tuple(he.dwAddress + i, he.th32HeapID, he.dwAddress); result.ReturnValue.Add(element); } } } } } return result; } /// /// Returns a collections of stats related to the heap of the current process object. If both heapID and startAddress are specified heapID takes precedence. /// /// display an extended set of /// The ID of the heap to display stats for. (optional) /// The start address of the specific heap block to display stats for in hexadecimal. (optional) /// returns a List object public ErcResult> HeapStatistics(bool extended = false, ulong heapID = 0, string hexStartAddress = "") { ErcResult> result = new ErcResult>(HeapProcess); if (hexStartAddress.Contains("0x") || hexStartAddress.Contains("0x") || hexStartAddress.Contains("x") || hexStartAddress.Contains("X")) { hexStartAddress = hexStartAddress.Replace("0x", ""); hexStartAddress = hexStartAddress.Replace("0X", ""); hexStartAddress = hexStartAddress.Replace("X", ""); hexStartAddress = hexStartAddress.Replace("x", ""); } ulong startAddress = 0; if(HeapProcess.ProcessMachineType == MachineType.I386) { try { startAddress = (uint)Convert.ToInt32(hexStartAddress, 16); } catch { } } else { try { startAddress = (ulong)Convert.ToInt64(hexStartAddress, 16); } catch { } } List heapStats = new List(); heapStats.Add("ProcessID = " + HeapProcess.ProcessID + Environment.NewLine); heapStats.Add("Number of heaps = " + HeapLists.Count + Environment.NewLine); if(heapID != 0) { heapStats.Add(" Heap ID = " + heapID + Environment.NewLine); } int count = 0; foreach(HEAPLIST32 hl in HeapLists) { count++; int heapEnts = 0; if(heapID == 0 && startAddress == 0) { heapStats.Add(" Heap " + count + " ID = " + hl.th32HeapID + Environment.NewLine); } foreach(HEAPENTRY32 he in HeapEntries) { if (heapID != 0) { if(he.th32HeapID == (IntPtr)heapID && hl.th32HeapID == (IntPtr)heapID) { if (HeapProcess.ProcessMachineType == MachineType.I386) { heapStats.Add(" Heap Start Address = 0x" + he.dwAddress.ToString("X8") + Environment.NewLine); heapStats.Add(" Heap Entry size = " + he.dwBlockSize.ToString() + Environment.NewLine); switch (he.dwFlags) { case 1: heapStats.Add(" Heap flags = LF32_FIXED" + Environment.NewLine); break; case 2: heapStats.Add(" Heap flags = LF32_FREE" + Environment.NewLine); break; case 4: heapStats.Add(" Heap flags = LF32_MOVEABLE" + Environment.NewLine); break; default: break; } } else { heapStats.Add(" Heap Start Address = " + he.dwAddress.ToString("X16") + Environment.NewLine); heapStats.Add(" Heap Entry size = " + he.dwBlockSize.ToString() + Environment.NewLine); switch (he.dwFlags) { case 1: heapStats.Add(" Heap flags = LF32_FIXED" + Environment.NewLine); break; case 2: heapStats.Add(" Heap flags = LF32_FREE" + Environment.NewLine); break; case 4: heapStats.Add(" Heap flags = LF32_MOVEABLE" + Environment.NewLine); break; default: break; } } heapEnts++; } } else if (startAddress != 0) { if(he.dwAddress == (IntPtr)startAddress) { if (HeapProcess.ProcessMachineType == MachineType.I386) { heapStats.Add(" Heap ID = " + hl.th32HeapID + Environment.NewLine); heapStats.Add(" Heap Start Address = " + he.dwAddress.ToString("X8") + Environment.NewLine); heapStats.Add(" Heap Entry size = " + he.dwBlockSize.ToString() + Environment.NewLine); switch (he.dwFlags) { case 1: heapStats.Add(" Heap flags = LF32_FIXED" + Environment.NewLine); result.ReturnValue = heapStats; return result; case 2: heapStats.Add(" Heap flags = LF32_FREE" + Environment.NewLine); result.ReturnValue = heapStats; return result; case 4: heapStats.Add(" Heap flags = LF32_MOVEABLE" + Environment.NewLine); result.ReturnValue = heapStats; return result; default: break; } } else { heapStats.Add(" Heap ID = " + hl.th32HeapID + Environment.NewLine); heapStats.Add(" Heap Start Address = " + he.dwAddress.ToString("X16") + Environment.NewLine); heapStats.Add(" Heap Entry size = " + he.dwBlockSize.ToString() + Environment.NewLine); switch (he.dwFlags) { case 1: heapStats.Add(" Heap flags = LF32_FIXED" + Environment.NewLine); result.ReturnValue = heapStats; return result; case 2: heapStats.Add(" Heap flags = LF32_FREE" + Environment.NewLine); result.ReturnValue = heapStats; return result; case 4: heapStats.Add(" Heap flags = LF32_MOVEABLE" + Environment.NewLine); result.ReturnValue = heapStats; return result; default: break; } } } } else if (he.th32HeapID == hl.th32HeapID) { if(extended == true) { if (HeapProcess.ProcessMachineType == MachineType.I386) { heapStats.Add(" Heap Start Address = " + he.dwAddress.ToString("X8") + Environment.NewLine); heapStats.Add(" Heap Entry size = " + he.dwBlockSize.ToString() + Environment.NewLine); switch (he.dwFlags) { case 1: heapStats.Add(" Heap flags = LF32_FIXED" + Environment.NewLine); break; case 2: heapStats.Add(" Heap flags = LF32_FREE" + Environment.NewLine); break; case 4: heapStats.Add(" Heap flags = LF32_MOVEABLE" + Environment.NewLine); break; default: break; } } else { heapStats.Add(" Heap Start Address = " + he.dwAddress.ToString("X16") + Environment.NewLine); heapStats.Add(" Heap Entry size = " + he.dwBlockSize.ToString() + Environment.NewLine); switch (he.dwFlags) { case 1: heapStats.Add(" Heap flags = LF32_FIXED" + Environment.NewLine); break; case 2: heapStats.Add(" Heap flags = LF32_FREE" + Environment.NewLine); break; case 4: heapStats.Add(" Heap flags = LF32_MOVEABLE" + Environment.NewLine); break; default: break; } } } heapEnts++; } } if(heapID != 0 || startAddress != 0) { if((IntPtr)heapID == hl.th32HeapID) { heapStats.Add(" Total number of entries in heap: " + heapEnts + Environment.NewLine); } } else { heapStats.Add(" Total number of entries in heap: " + heapEnts + Environment.NewLine); } } result.ReturnValue = heapStats; return result; } /// /// Lists all HeapIDs associated with a process. /// /// Returns an ErcResult>" public ErcResult> HeapIDs() { ErcResult> result = new ErcResult>(HeapProcess); result.ReturnValue = new List(); foreach(HEAPLIST32 hl in HeapLists) { result.ReturnValue.Add((ulong)hl.th32HeapID); } if(result.ReturnValue.Count == 0) { result.Error = new ERCException("Error: No heap ids found associated with this process."); } return result; } #endregion } } ================================================ FILE: ERC/ERC/Module_Info.cs ================================================ using ERC.Structures; using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Runtime.InteropServices; namespace ERC { /// /// Contains all information relating to a specific module. /// public class ModuleInfo { #region Class Variables /// /// Module name. /// public string ModuleName { get; private set; } /// /// Module path. /// public string ModulePath { get; private set; } /// /// Module version. /// public string ModuleVersion { get; private set; } /// /// Module product. /// public string ModuleProduct { get; private set; } /// /// Memory protection of this module. /// public uint ModuleProtection { get; private set; } /// /// Module base pointer. /// public IntPtr ModuleBase { get; private set; } /// /// Module entry point. /// public IntPtr ModuleEntry { get; private set; } /// /// Module image base. /// public IntPtr ModuleImageBase { get; private set; } /// /// Module size. /// public int ModuleSize { get; private set; } /// /// Module supports ASLR. /// public bool ModuleASLR { get; private set; } /// /// Module supports SafeSEH /// public bool ModuleSafeSEH { get; private set; } /// /// Module can be rebased. /// public bool ModuleRebase { get; private set; } /// /// Module is DEP enabled. /// public bool ModuleNXCompat { get; private set; } /// /// Module is an OS dll. /// public bool ModuleOsDll { get; private set; } /// /// Process where the module is loaded. /// public Process ModuleProcess { get; private set; } /// /// Associated ErcCore object. /// public ErcCore ModuleCore { get; private set; } /// /// Machine type of the module. /// public MachineType ModuleMachineType { get; private set; } internal IMAGE_DOS_HEADER ImageDosHeader = new IMAGE_DOS_HEADER(); internal IMAGE_FILE_HEADER ImageFileHeader = new IMAGE_FILE_HEADER(); internal IMAGE_NT_HEADERS32 ImageNTHeaders32 { get; private set; } internal IMAGE_NT_HEADERS64 ImageNTHeaders64 { get; private set; } internal IMAGE_OPTIONAL_HEADER32 ImageOptionalHeader32 { get; private set; } internal IMAGE_OPTIONAL_HEADER64 ImageOptionalHeader64 { get; private set; } internal IMAGE_LOAD_CONFIG_DIRECTORY32 ImageConfigDir32 { get; private set; } internal IMAGE_LOAD_CONFIG_DIRECTORY64 ImageConfigDir64 { get; private set; } internal LOADED_IMAGE loadedImage = new LOADED_IMAGE(); /// /// An errpr was encountered whilst processing the module. /// public bool ModuleFailed = false; #endregion #region Constructor /// /// Constructor for the ModuleInfo object. Takes (string)modules filepath (IntPtr)module handle (Process)Process from which the module is loaded /// /// Filepath of the module /// Handle to the module /// Process where the module is loaded /// An ErcCore object internal unsafe ModuleInfo(string module, IntPtr ptr, Process process, ErcCore core) { try { ModuleCore = core; ModuleProcess = process; ModuleName = FileVersionInfo.GetVersionInfo(module).InternalName; ModulePath = FileVersionInfo.GetVersionInfo(module).FileName; ModuleBase = ptr; FileInfo fileInfo = new FileInfo(ModulePath); FileStream file = fileInfo.Open(FileMode.Open, FileAccess.Read, FileShare.Read); PopulateHeaderStructs(file); if (!string.IsNullOrEmpty(FileVersionInfo.GetVersionInfo(module).FileVersion)) { ModuleVersion = FileVersionInfo.GetVersionInfo(module).FileVersion.Split(' ')[0]; } else { ModuleVersion = ""; } ModuleProduct = FileVersionInfo.GetVersionInfo(module).ProductName; if (ModuleMachineType == MachineType.I386) { ModuleEntry = (IntPtr)ImageOptionalHeader32.AddressOfEntryPoint; ModuleSize = (int)ImageOptionalHeader32.SizeOfImage; ModuleImageBase = (IntPtr)ImageOptionalHeader32.ImageBase; byte[] dllByte = BitConverter.GetBytes(ImageOptionalHeader32.DllCharacteristics); BitArray bits = new BitArray(dllByte); for (int i = 0; i < bits.Count; i++) { if (bits[i] == true && i == 6) { ModuleASLR = true; } else { ModuleASLR = false; } if (bits[i] == true && i == 8) { ModuleNXCompat = true; } else { ModuleNXCompat = false; } } if(ModuleMachineType == MachineType.I386) { PopulateConfigStruct(); if (ImageConfigDir32.SEHandlerCount == 0 && ImageConfigDir32.SEHandlerTable == 0) { ModuleSafeSEH = false; } else { ModuleSafeSEH = true; } } else { ModuleSafeSEH = true; } } else if (ModuleMachineType == MachineType.x64) { ModuleEntry = (IntPtr)ImageOptionalHeader64.AddressOfEntryPoint; ModuleSize = (int)ImageOptionalHeader64.SizeOfImage; ModuleImageBase = (IntPtr)ImageOptionalHeader64.ImageBase; byte[] dllByte = BitConverter.GetBytes(ImageOptionalHeader64.DllCharacteristics); BitArray bits = new BitArray(dllByte); for (int i = 0; i < bits.Count; i++) { if (bits[i] == true && i == 6) { ModuleASLR = true; } else if (bits[i] == false && i == 6) { ModuleASLR = false; } if (bits[i] == true && i == 8) { ModuleNXCompat = true; } else if (bits[i] == false && i == 8) { ModuleNXCompat = false; } } PopulateConfigStruct(); if(ImageConfigDir64.SEHandlerCount == 0 && ImageConfigDir64.SEHandlerTable == 0) { ModuleSafeSEH = false; } else { ModuleSafeSEH = true; } } else { ModuleFailed = true; throw new ERCException("Unsupported machine type: " + ModuleMachineType.ToString()); } if (ModuleProduct == "Microsoft® Windows® Operating System") { ModuleOsDll = true; } else { ModuleOsDll = false; } if (ModuleImageBase != ptr) { ModuleRebase = true; } else { ModuleRebase = false; } long MaxAddress = 0x7fffffff; long address = (long)ModuleBase; if (!ProcessInfo.Is64Bit(process)) { List ProcessMemoryBasicInfo32 = new List(); long oldAddress = 0; do { ERC.Structures.MEMORY_BASIC_INFORMATION32 m; int result = ErcCore.VirtualQueryEx32(ModuleProcess.Handle, (IntPtr)address, out m, (uint)Marshal.SizeOf(typeof(MEMORY_BASIC_INFORMATION32))); if (address == (long)m.BaseAddress + (long)m.RegionSize) break; address = (long)m.BaseAddress + (long)m.RegionSize; if(oldAddress > address) { address = long.MaxValue; } oldAddress = address; ModuleProtection = m.AllocationProtect; } while (address <= MaxAddress); } else { List ProcessMemoryBasicInfo64 = new List(); long oldAddress = 0; do { ERC.Structures.MEMORY_BASIC_INFORMATION64 m; int result = ErcCore.VirtualQueryEx64(ModuleProcess.Handle, (IntPtr)address, out m, (uint)Marshal.SizeOf(typeof(MEMORY_BASIC_INFORMATION64))); if (address == (long)m.BaseAddress + (long)m.RegionSize) break; address = (long)m.BaseAddress + (long)m.RegionSize; if (oldAddress > address) { address = long.MaxValue; } oldAddress = address; ModuleProtection = m.AllocationProtect; } while (address <= MaxAddress); } } catch (Exception e) { ErcResult ExceptionLogger = new ErcResult(ModuleCore); ExceptionLogger.Error = e; ExceptionLogger.LogEvent(); ModuleFailed = true; } } private unsafe void PopulateHeaderStructs(FileStream fin) { byte[] Data = new byte[4096]; int iRead = fin.Read(Data, 0, 4096); fin.Flush(); fin.Close(); fixed (byte* p_Data = Data) { IMAGE_DOS_HEADER* idh = (IMAGE_DOS_HEADER*)p_Data; IMAGE_NT_HEADERS32* inhs = (IMAGE_NT_HEADERS32*)(idh->nt_head_ptr + p_Data); ModuleMachineType = (MachineType)inhs->FileHeader.Machine; if (ModuleMachineType == MachineType.I386) { IMAGE_NT_HEADERS32* inhs32 = (IMAGE_NT_HEADERS32*)(idh->nt_head_ptr + p_Data); ImageFileHeader = inhs32->FileHeader; ModuleMachineType = (MachineType)inhs32->FileHeader.Machine; ImageOptionalHeader32 = inhs32->OptionalHeader; ModuleImageBase = (IntPtr)inhs32->OptionalHeader.ImageBase; ImageNTHeaders32 = new IMAGE_NT_HEADERS32 { Signature = inhs32->Signature, FileHeader = inhs32->FileHeader, OptionalHeader = inhs32->OptionalHeader }; byte[] bytes = new byte[256]; var ret = ErcCore.ReadProcessMemory(ModuleProcess.Handle, (IntPtr)((uint)ModuleBase + ImageOptionalHeader32.LoadConfigTable.VirtualAddress), bytes, 256, out int BytesRead); if (BitConverter.ToUInt32(bytes, 58) > 0 || BitConverter.ToUInt32(bytes, 62) > 0) { ModuleSafeSEH = true; } } else if (ModuleMachineType == MachineType.x64) { IMAGE_NT_HEADERS64* inhs64 = (IMAGE_NT_HEADERS64*)(idh->nt_head_ptr + p_Data); ImageFileHeader = inhs64->FileHeader; ImageOptionalHeader64 = inhs64->OptionalHeader; ModuleImageBase = (IntPtr)inhs64->OptionalHeader.ImageBase; ImageNTHeaders64 = new IMAGE_NT_HEADERS64 { Signature = inhs64->Signature, FileHeader = inhs64->FileHeader, OptionalHeader = inhs64->OptionalHeader }; byte[] bytes = new byte[256]; var ret = ErcCore.ReadProcessMemory(ModuleProcess.Handle, (IntPtr)((long)ModuleBase + (long)ImageOptionalHeader64.LoadConfigTable.VirtualAddress), bytes, 256, out int BytesRead); if (BitConverter.ToUInt64(bytes, 88) > 0 || BitConverter.ToUInt64(bytes, 96) > 0) { ModuleSafeSEH = true; } } else { ModuleFailed = true; } } } private void PopulateConfigStruct() { string path = Path.GetDirectoryName(ModulePath); string name = Path.GetFileName(ModulePath); bool dll = true; if(Path.GetExtension(ModulePath) != ".dll" && Path.GetExtension(ModulePath) != ".DLL") { dll = false; } var MaLRet = ErcCore.MapAndLoad(name, path, out loadedImage, dll, true); var modPtr = ErcCore.ImageLoad(name, path); if (ModuleMachineType == MachineType.I386) { IMAGE_LOAD_CONFIG_DIRECTORY32 ImageConfigDir = new IMAGE_LOAD_CONFIG_DIRECTORY32(); var check = ErcCore.GetImageConfigInformation32(ref loadedImage, ref ImageConfigDir); } else if (ModuleMachineType == MachineType.x64) { IMAGE_LOAD_CONFIG_DIRECTORY64 ImageConfigDir = new IMAGE_LOAD_CONFIG_DIRECTORY64(); var check = ErcCore.GetImageConfigInformation64(ref loadedImage, ref ImageConfigDir); } } #endregion #region SearchModule /// /// Searches for a string of bytes within a specific module. Takes a byte array to be searched for. /// /// A byte array to be searched for /// Returns ERC_Result of pointers to the search term public ErcResult> SearchModule(byte[] searchBytes) { ErcResult> results = new ErcResult>(ModuleCore); List ptrs = new List(); IntPtr baseAddress = ModuleBase; byte[] buffer = new byte[ModuleSize]; int bytesread = 0; ErcCore.ReadProcessMemory(ModuleProcess.Handle, ModuleBase, buffer, buffer.Length, out bytesread); List positions = SearchBytePattern(searchBytes, buffer); for(int i = 0; i < positions.Count; i++) { ptrs.Add((IntPtr)(positions[i] + (long)ModuleBase)); } results.ReturnValue = ptrs; return results; } private List SearchBytePattern(byte[] pattern, byte[] bytes) { List positions = new List(); int patternLength = pattern.Length; int totalLength = bytes.Length; byte firstMatchByte = pattern[0]; for (int i = 0; i < totalLength; i++) { if (firstMatchByte == bytes[i] && totalLength - i >= patternLength) { byte[] match = new byte[patternLength]; Array.Copy(bytes, i, match, 0, patternLength); if (match.SequenceEqual(pattern)) { positions.Add(i); i += patternLength - 1; } } } return positions; } #endregion #region ToString /// /// Override of the ToString method. Provides a data associated with the module. /// /// A string containing relevant data. public override string ToString() { string ret = ""; ret += "Module Name = " + ModuleName + Environment.NewLine; ret += "Module Path = " + ModulePath + Environment.NewLine; ret += "Module Version = " + ModuleVersion + Environment.NewLine; ret += "Module Produce = " + ModuleProduct + Environment.NewLine; if (ModuleMachineType == MachineType.x64) { ret += "Module Handle = " + "0x" + ModuleBase.ToString("x16") + Environment.NewLine; ret += "Module Entrypoint = " + "0x" + ModuleEntry.ToString("x16") + Environment.NewLine; ret += "Module Image Base = " + "0x" + ModuleImageBase.ToString("x16") + Environment.NewLine; } else { ret += "Module Handle = " + "0x" + ModuleBase.ToString("x8") + Environment.NewLine; ret += "Module Entrypoint = " + "0x" + ModuleEntry.ToString("x8") + Environment.NewLine; ret += "Module Image Base = " + "0x" + ModuleImageBase.ToString("x8") + Environment.NewLine; } ret += "Module Size = " + ModuleSize + Environment.NewLine; ret += "Module ASLR = " + ModuleASLR + Environment.NewLine; ret += "Module SafeSEH = " + ModuleSafeSEH + Environment.NewLine; ret += "Module Rebase = " + ModuleRebase + Environment.NewLine; ret += "Module NXCompat = " + ModuleNXCompat + Environment.NewLine; ret += "Module OS DLL = " + ModuleOsDll + Environment.NewLine; return ret; } #endregion } } ================================================ FILE: ERC/ERC/Opcode_Assembler.cs ================================================ using System; using System.Collections.Generic; using Reloaded.Assembler; namespace ERC.Utilities { /// /// OpcodeAssembler class, can be declared and inherit from a ProcessInfo object to inherit the values of the current process or be called as /// a static function to assemble instructions. /// public class OpcodeAssembler : ProcessInfo { /// /// Constructor. /// /// ProcessInfo object to be inherited from. public OpcodeAssembler(ProcessInfo parent) : base(parent) { } /// /// Takes either an array or list of strings containing assembly instructions and returns the associated opcodes. /// /// The instructions to be assembled /// Returns an ErcResult byte array containing the assembled instructions public ErcResult AssembleOpcodes(List instructions) { ErcResult result = new ErcResult(ProcessCore); List mnemonics = new List(); if (ProcessMachineType == MachineType.I386) { mnemonics.Add("use32"); } else if (ProcessMachineType == MachineType.x64) { mnemonics.Add("use64"); } for (int i = 0; i < instructions.Count; i++) { mnemonics.Add(instructions[i]); } var asm = new Assembler(); try { result.ReturnValue = asm.Assemble(mnemonics); asm.Dispose(); } catch (Exception e) { result.Error = e; result.LogEvent(); asm.Dispose(); GC.Collect(); return result; } GC.Collect(); return result; } /// /// Takes either an array or list of strings containing assembly instructions, a MachineType of I386 or x64, /// an instance of the ERC_Core object and returns the associated opcodes. /// /// The instructions to be assemble=d /// a ERC.MachineType of either I386 or x64 /// Returns an ERC_Result byte array containing the assembled instructions public static ErcResult AssembleOpcodes(List instructions, MachineType machineType) { ErcResult result = new ErcResult(new ErcCore()); List mnemonics = new List(); if (machineType == MachineType.I386) { mnemonics.Add("use32"); } else if (machineType == MachineType.x64) { mnemonics.Add("use64"); } for(int i = 0; i < instructions.Count; i++) { mnemonics.Add(instructions[i]); } var asm = new Assembler(); try { result.ReturnValue = asm.Assemble(mnemonics); asm.Dispose(); } catch(Exception e) { result.Error = e; result.LogEvent(); asm.Dispose(); GC.Collect(); return result; } GC.Collect(); return result; } } } ================================================ FILE: ERC/ERC/Opcode_Disassembler.cs ================================================ using System; using System.Linq; namespace ERC.Utilities { /// /// OpcodeDisassembler class, can be declared and inherit from a ProcessInfo object to inherit the values of the current process or be called as /// a static function to disassemble opcodes. /// public class OpcodeDisassembler : ProcessInfo { /// /// Constructor. /// /// ProcessInfo object to be inherited from. public OpcodeDisassembler(ProcessInfo parent) : base(parent) { } /// /// Disassembles opcodes into the associated instructions. Takes a byte array containing opcodes. /// /// The opcodes to be disassembled /// Returns an ERC_Result containing associated instructions. public ErcResult Disassemble(byte[] opcodes) { ErcResult result = new ErcResult(ProcessCore); SharpDisasm.Disassembler.Translator.IncludeAddress = true; SharpDisasm.Disassembler.Translator.IncludeBinary = true; SharpDisasm.Disassembler disasm; SharpDisasm.ArchitectureMode mode; try { if (ProcessMachineType == MachineType.I386) { mode = SharpDisasm.ArchitectureMode.x86_32; } else if (ProcessMachineType == MachineType.x64) { mode = SharpDisasm.ArchitectureMode.x86_64; } else { throw new ERCException("User input error: Machine Type is invalid, must be ERC.MachineType.x86_64 or ERC.MachineType.x86_32"); } } catch (ERCException e) { result.Error = e; result.LogEvent(); return result; } try { disasm = new SharpDisasm.Disassembler( HexStringToByteArray(BitConverter.ToString(opcodes).Replace("-", "")), mode, 0, true); } catch (Exception e) { result.Error = e; result.LogEvent(e); return result; } foreach (var insn in disasm.Disassemble()) { var mne = insn.ToString().Split(new string[] { " " }, StringSplitOptions.None); result.ReturnValue += mne[mne.Length - 1].Trim() + Environment.NewLine; } return result; } /// /// Disassembles opcodes into the associated instructions. Takes a byte array containing opcodes, a MachineType of I386 or x64, /// an instance of the ERC_Core object and returns an ERC_Result containing associated instructions. /// /// A byte array containing opcodes to be disassembled /// a ERC.MachineType of either I386 or x64 /// Returns an ERC_Result containing associated instructions. public static ErcResult Disassemble(byte[] opcodes, MachineType machineType) { ErcResult result = new ErcResult(new ErcCore()); SharpDisasm.Disassembler.Translator.IncludeAddress = true; SharpDisasm.Disassembler.Translator.IncludeBinary = true; SharpDisasm.Disassembler disasm; SharpDisasm.ArchitectureMode mode; try { if (machineType == MachineType.I386) { mode = SharpDisasm.ArchitectureMode.x86_32; } else if (machineType == MachineType.x64) { mode = SharpDisasm.ArchitectureMode.x86_64; } else { throw new ERCException("User input error: Machine Type is invalid, must be ERC.MachineType.x86_64 or ERC.MachineType.x86_32"); } } catch(ERCException e) { result.Error = e; result.LogEvent(); return result; } try { disasm = new SharpDisasm.Disassembler( HexStringToByteArray(BitConverter.ToString(opcodes).Replace("-", "")), mode, 0, true); } catch(Exception e) { result.Error = e; result.LogEvent(e); return result; } foreach (var insn in disasm.Disassemble()) { var mne = insn.ToString().Split(new string[] { " " }, StringSplitOptions.None); result.ReturnValue += mne[mne.Length - 1].Trim() + Environment.NewLine; } return result; } /// /// Disassembles opcodes into the associated instructions. Takes a byte array containing opcodes, a MachineType of I386 or x64, /// an instance of the ERC_Core object and returns an ERC_Result containing associated instructions. /// /// A byte array containing opcodes to be disassembled /// a ERC.MachineType of either I386 or x64 /// a ErcCore object /// Returns an ERC_Result containing associated instructions. public static ErcResult Disassemble(byte[] opcodes, MachineType machineType, ErcCore core) { ErcResult result = new ErcResult(core); SharpDisasm.Disassembler.Translator.IncludeAddress = true; SharpDisasm.Disassembler.Translator.IncludeBinary = true; SharpDisasm.Disassembler disasm; SharpDisasm.ArchitectureMode mode; try { if (machineType == MachineType.I386) { mode = SharpDisasm.ArchitectureMode.x86_32; } else if (machineType == MachineType.x64) { mode = SharpDisasm.ArchitectureMode.x86_64; } else { throw new ERCException("User input error: Machine Type is invalid, must be ERC.MachineType.x86_64 or ERC.MachineType.x86_32"); } } catch (ERCException e) { result.Error = e; result.LogEvent(); return result; } try { disasm = new SharpDisasm.Disassembler( HexStringToByteArray(BitConverter.ToString(opcodes).Replace("-", "")), mode, 0, true); } catch (Exception e) { result.Error = e; result.LogEvent(e); return result; } foreach (var insn in disasm.Disassemble()) { var mne = insn.ToString().Split(new string[] { " " }, StringSplitOptions.None); result.ReturnValue += mne[mne.Length - 1].Trim() + Environment.NewLine; } return result; } private static byte[] HexStringToByteArray(string hex) { return Enumerable.Range(0, hex.Length) .Where(x => x % 2 == 0) .Select(x => System.Convert.ToByte(hex.Substring(x, 2), 16)) .ToArray(); } } } ================================================ FILE: ERC/ERC/Pattern_Tools.cs ================================================ using System; using System.IO; using System.Text; using System.Text.RegularExpressions; namespace ERC.Utilities { /// /// Static class used to build a non repeating pattern and identify the position of a string in a non repeating pattern. /// public static class PatternTools { #region string Constants private const string uppercase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; private const string lowercase = "abcdefghijklmnopqrstuvwxyz"; #endregion #region Pattern Create /// /// Creates a string of non repeating characters. /// /// The length of the pattern to be created as integer /// An ErcCore object /// (Optional) bool specifying whether the extended character set should be used /// Returns an ErcResult string containing the generated pattern public static ErcResult PatternCreate(int length, ErcCore core, bool extended = false) { string digits = "0123456789"; ErcResult result = new ErcResult(core); if (extended == true) { digits += ": ,.;+=-_!&()#@'*^[]%$?"; if(length > 66923) { result.Error = new ERCException("User input error: Pattern length must be less that 66923"); result.LogEvent(); return result; } } else { if(length > 20277) { result.Error = new ERCException("User input error: Pattern length must be less that 20277. Add the extended flag to create larger strings."); result.LogEvent(); return result; } } result.ReturnValue = ""; if (length < 1) { result.Error = new ERCException("User Input Error: Pattern length must be greate than 0."); result.LogEvent(); return result; } for (int i = 0; i < uppercase.Length; i++) { for (int j = 0; j < lowercase.Length; j++) { for (int k = 0; k < digits.Length; k++) { char pos1 = uppercase[i]; char pos2 = lowercase[j]; char pos3 = digits[k]; if (result.ReturnValue.Length > length) { result.Error = new ERCException("Procedural Error: Pattern string has exceeded the length supplied"); result.ReturnValue = ""; return result; } if (result.ReturnValue.Length == length) { return result; } if (result.ReturnValue.Length < length - 2) { result.ReturnValue += pos1; result.ReturnValue += pos2; result.ReturnValue += pos3; if (result.ReturnValue.Length == length) { return result; } } else if (result.ReturnValue.Length < length - 1) { result.ReturnValue += pos1; result.ReturnValue += pos2; if (result.ReturnValue.Length == length) { return result; } } else if (result.ReturnValue.Length < length) { result.ReturnValue += pos1; if (result.ReturnValue.Length == length) { return result; } } } } } result.Error = new ERCException("An unknown error has occured. Function exited incorrectly. Function: ERC.Pattern_Tools.Pattern_Create"); result.LogEvent(); return result; } #endregion #region Pattern Offset /// /// Takes a string of characters and returns the location of the first character in a pattern created by Pattern_Create. /// /// The pattern to be searched for. /// An ErcCore object /// (Optional) bool specifying whether the extended character set should be used /// Returns an ErcResult int containing the offset of the supplied pattern within the generated pattern public static ErcResult PatternOffset(string pattern, ErcCore core, bool extended = false) { //create string with reversed version of pattern to be searched for. char[] reversedChars = pattern.ToCharArray(); Array.Reverse(reversedChars); string reversed = new string(reversedChars); //Create pattern to search within. Either extended or normal. string digits = "0123456789"; string patternFull; if (extended == true) { digits += ": ,.;+=-_!&()#@'*^[]%$?"; patternFull = File.ReadAllText(core.PatternExtendedPath); } else { patternFull = File.ReadAllText(core.PatternStandardPath); } ErcResult result = new ErcResult(core); if (pattern.Length < 3) { result.Error = new ERCException("User Input Error: Pattern length must be 3 characters or longer."); result.LogEvent(); return result; } if (patternFull.Contains(pattern)) { result.ReturnValue = "Value found at position " + patternFull.IndexOf(pattern).ToString() + " in pattern."; return result; } else if (patternFull.Contains(reversed)) { result.ReturnValue = "Value found reversed at position " + patternFull.IndexOf(reversed).ToString() + " in pattern."; return result; } bool validHexString = true; foreach(char c in pattern) { if((c < '0' || c > '9') && (c < 'a' || c > 'f') && (c < 'A' || c > 'F')) { validHexString = false; } } if(validHexString == true) { byte[] patternBytes = ERC.Utilities.Convert.HexToBytes(pattern); byte[] patternBytesReversed = ERC.Utilities.Convert.HexToBytes(reversed); byte[] patternFullBytes = Encoding.ASCII.GetBytes(patternFull); string hexString = BitConverter.ToString(patternBytes).Replace("-", ""); string hexStringReversed = BitConverter.ToString(patternBytesReversed).Replace("-", ""); string hexPatternFull = BitConverter.ToString(patternFullBytes).Replace("-", ""); if (hexPatternFull.Contains(hexString)) { result.ReturnValue = "Value found at position " + (hexPatternFull.IndexOf(hexString) / 2).ToString() + " in pattern."; return result; } else if (hexPatternFull.Contains(hexStringReversed)) { result.ReturnValue = "Value found reversed at position " + (hexPatternFull.IndexOf(hexStringReversed) / 2).ToString() + " in pattern."; return result; } } result.Error = new ERCException("Error: Value not found."); result.ReturnValue = "Value not found in pattern."; return result; } #endregion } } ================================================ FILE: ERC/ERC/Payloads.cs ================================================ using System; using System.Collections.Generic; using System.IO; namespace ERC.Utilities { /// /// A collecton of methods which generate payloads. /// public static class Payloads { private static byte[] ByteArray = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, }; #region Egg Hunters /// /// Default egg hunter tag. /// public static string DefaultEgg = "ERCD"; /// /// A 64 bit egg hunter. /// public static byte[] EggHunter641 = { 0x8C, 0xCB, 0x80, 0xFB, 0x23, 0x33, 0xD2, 0x66, 0x81, 0xCA, 0xFF, 0x0F, 0x33, 0xDB, 0x42, 0x52, 0x53, 0x53, 0x53, 0x6A, 0x29, 0x58, 0xB3, 0xC0, 0x64, 0xFF, 0x13, 0x83, 0xC4, 0x0C, 0x5A, 0x3C, 0x05, 0x74, 0xE4, 0xB8, 0x45, 0x52, 0x43, 0x44, 0x89, 0xD7, 0xAF, 0x75, 0xE1, 0xAF, 0x75, 0xDE, 0xFF, 0xE7 }; /// /// A second 64 bit egg hunter. /// public static byte[] EggHunter642 = { 0x54, 0x59, 0x48, 0x83, 0xc1, 0xff, 0x48, 0xff, 0xc1, 0x81, 0x79, 0xfc, 0x45, 0x52, 0x43, 0x44, 0x75, 0xf4, 0xff, 0xe1 }; /// /// A 32 bit egg hunter. /// public static byte[] EggHunter32 = { 0x66, 0x81, 0xca, 0xff, 0x0f, 0x42, 0x52, 0x6a, 0x02, 0x58, 0xcd, 0x2e, 0x3c, 0x05, 0x5a, 0x74, 0xef, 0xb8, 0x45, 0x52, 0x43, 0x44, 0x8b, 0xfa, 0xaf, 0x75, 0xea, 0xaf, 0x75, 0xe7, 0xff, 0xe7 }; /// /// An egg hunter that will work on 32 bit systems or 32 bit processes running under WOW64. /// public static byte[] EggHunterWOW64 = { 0x66, 0x8c, 0xcb, 0x80, 0xfb, 0x23, 0x75, 0x08, 0x31, 0xdb, 0x53, 0x53, 0x53, 0x53, 0xb3, 0xc0, 0x66, 0x81, 0xca, 0xff, 0x0f, 0x42, 0x52, 0x80, 0xfb, 0xc0, 0x74, 0x19, 0x6a, 0x02, 0x58, 0xcd, 0x2e, 0x5a, 0x3c, 0x05, 0x74, 0xea, 0xb8, 0x45, 0x52, 0x43, 0x44, 0x89, 0xd7, 0xaf, 0x75, 0xe5, 0xaf, 0x75, 0xe2, 0xff, 0xe7, 0x6a, 0x26, 0x58, 0x31, 0xc9, 0x89, 0xe2, 0x64, 0xff, 0x13, 0x5e, 0x5a, 0xeb, 0xdf }; #endregion #region Byte Array Constructor /// /// Creates an array of all possible byte values except those passed to the function. /// /// Takes a byte array of bytes to be excluded /// Returns an array of all other possible bytes. public static byte[] ByteArrayConstructor(byte[] unwantedBytes) { byte[] bytes; if(unwantedBytes != null) { bytes = new byte[ByteArray.Length - unwantedBytes.Length]; } else { bytes = new byte[ByteArray.Length]; } int bytesCounter = 0; for(int i = 0; i < ByteArray.Length; i++) { bool addByte = true; if(unwantedBytes != null) { for (int j = 0; j < unwantedBytes.Length; j++) { if (ByteArray[i].Equals(unwantedBytes[j])) { addByte = false; } } } if(addByte == true) { bytes[bytesCounter] = ByteArray[i]; bytesCounter++; } } return bytes; } #endregion #region Egg Hunter Constructor /// /// Generates a selection of EggHunter payloads. A custom tag can be specified, if no tag is specified EggHunters will search for the default tag (ERCD) /// /// A custom tag which the egg hunters will search for. /// Returns a dictionary containing a list of EggHunters and string detailing them public static Dictionary EggHunterConstructor(string tag = null) { Dictionary eggHunters = new Dictionary(); string eggHunter641Description = "64 Bit Egg Hunter 1:" + Environment.NewLine + "Usage: To be used on 64 bit processes running on 64 bit systems only, not on 32 bit processes running on a 64 bit system." + Environment.NewLine; string eggHunter642Description = "64 Bit Egg Hunter 2:" + Environment.NewLine + "Usage: To be used on 64 bit processes running on 64 bit systems only, not on 32 bit processes running on a 64 bit system." + Environment.NewLine; string eggHunter32Description = "32 Bit Egg Hunter:" + Environment.NewLine + "Usage: To be used on 32 bit systems only, not on 32 bit processes running on a 64 bit system." + Environment.NewLine; string eggHunterWOW64Description = "WOW64 Egg Hunter:" + Environment.NewLine + "Usage: To be used on 32 bit processes running on a 64 bit system. Can also be used on 32 bit systems." + Environment.NewLine; if (tag != null) { if (tag.Length != 4) { tag = null; } } if (tag != null) { byte[] bytes1 = new byte[EggHunter641.Length]; Array.Copy(EggHunter641, 0, bytes1, 0, 36); bytes1[36] = (byte)tag[0]; bytes1[37] = (byte)tag[1]; bytes1[38] = (byte)tag[2]; bytes1[39] = (byte)tag[3]; Array.Copy(EggHunter641, 40, bytes1, 40, EggHunter641.Length - 40); eggHunters.Add(eggHunter641Description, bytes1);//Change this to be a description of the egghunter and where to use it byte[] bytes2 = new byte[EggHunter642.Length]; Array.Copy(EggHunter642, 0, bytes2, 0, 12); bytes2[12] = (byte)tag[0]; bytes2[13] = (byte)tag[1]; bytes2[14] = (byte)tag[2]; bytes2[15] = (byte)tag[3]; Array.Copy(EggHunter642, 16, bytes2, 16, EggHunter642.Length - 16); eggHunters.Add(eggHunter642Description, bytes2);//Change this to be a description of the egghunter and where to use it byte[] bytes3 = new byte[EggHunter32.Length]; Array.Copy(EggHunter32, 0, bytes3, 0, 18); bytes3[18] = (byte)tag[0]; bytes3[19] = (byte)tag[1]; bytes3[20] = (byte)tag[2]; bytes3[21] = (byte)tag[3]; Array.Copy(EggHunter32, 22, bytes3, 22, EggHunter32.Length - 22); eggHunters.Add(eggHunter32Description, bytes3);//Change this to be a description of the egghunter and where to use it byte[] bytes4 = new byte[EggHunterWOW64.Length]; Array.Copy(EggHunterWOW64, 0, bytes4, 0, 39); bytes4[39] = (byte)tag[0]; bytes4[40] = (byte)tag[1]; bytes4[41] = (byte)tag[2]; bytes4[42] = (byte)tag[3]; Array.Copy(EggHunterWOW64, 43, bytes4, 43, EggHunterWOW64.Length - 43); eggHunters.Add(eggHunterWOW64Description, bytes4);//Change this to be a description of the egghunter and where to use it } else { eggHunters.Add(eggHunter641Description, EggHunter641); eggHunters.Add(eggHunter642Description, EggHunter642); eggHunters.Add(eggHunter32Description, EggHunter32); eggHunters.Add(eggHunterWOW64Description, EggHunterWOW64); } return eggHunters; } #endregion #region SEH Hop Search /// /// Finds all instances of POP X POP X RET in a given byte array. /// /// Byte array to be searched /// Returns an array of integers containing the offsets of the instruction sets. public static List PopPopRet(byte[] data) { List locations = new List(); List assemblies = new List(); byte[] R8 = new byte[] { 0x58, 0x41 }; byte[] R9 = new byte[] { 0x59, 0x41 }; byte[] R10 = new byte[] { 0x5A, 0x41 }; byte[] R11 = new byte[] { 0x5B, 0x41 }; byte[] R12 = new byte[] { 0x5C, 0x41 }; byte[] R13 = new byte[] { 0x5D, 0x41 }; byte[] R14 = new byte[] { 0x5E, 0x41 }; byte[] R15 = new byte[] { 0x5F, 0x41 }; assemblies.Add(BitConverter.GetBytes(0xC3)); assemblies.Add(BitConverter.GetBytes(0x58)); assemblies.Add(BitConverter.GetBytes(0x5D)); assemblies.Add(BitConverter.GetBytes(0x59)); assemblies.Add(BitConverter.GetBytes(0x5A)); assemblies.Add(BitConverter.GetBytes(0x5C)); assemblies.Add(BitConverter.GetBytes(0x5D)); assemblies.Add(BitConverter.GetBytes(0x5E)); assemblies.Add(BitConverter.GetBytes(0x5F)); assemblies.Add(R8); assemblies.Add(R9); assemblies.Add(R10); assemblies.Add(R11); assemblies.Add(R12); assemblies.Add(R13); assemblies.Add(R14); assemblies.Add(R15); assemblies.Add(BitConverter.GetBytes(0x5F)); assemblies.Add(BitConverter.GetBytes(0x5E)); assemblies.Add(BitConverter.GetBytes(0x5B)); assemblies.Add(BitConverter.GetBytes(0x5A)); assemblies.Add(BitConverter.GetBytes(0x59)); assemblies.Add(BitConverter.GetBytes(0x58)); assemblies.Add(BitConverter.GetBytes(0x5D)); assemblies.Add(BitConverter.GetBytes(0x5C)); for(int i = 2; i < data.Length; i++) { bool complete = false; if (data[i].Equals(assemblies[0][0])) { for(int j = 1; j < assemblies.Count; j++) { if(data[i - 1].Equals(assemblies[j][0])) { if (assemblies[j].Length < 4) { for (int k = 1; k < assemblies.Count; k++) { if (data[i - 2].Equals(assemblies[k][0]) && assemblies[k].Length < 4 && complete == false) { locations.Add(i - 2); complete = true; } else if(data[i - 2].Equals(assemblies[k][0])) { if (data[i - 3].Equals(0x41) && complete == false) { locations.Add(i - 3); complete = true; } } } } else { if (data[i - 2].Equals(0x41)) { for (int k = 1; k < assemblies.Count; k++) { if (data[i - 3].Equals(assemblies[k][0]) && complete == false) { if(assemblies[k].Length < 4) { locations.Add(i - 3); complete = true; } else if(assemblies[k].Length == 4 && data[i - 4].Equals(0x41) && complete == false) { locations.Add(i - 4); complete = true; } } } } } } } } } return locations; } #endregion #region Byte Array Compare /// /// Compares a byte array with an area in memory of equal size. This method should be used in conjunction with the ByteArrayConstructor to identify /// bytes which can not be passed into a program without corrupting the input. /// /// The process to compare memory from /// The address at which to start the comparison /// The byte array containing the bytes to be compared /// Returns a Tuple containing a bool which is true if the comparison was identical and false if it was not, a byte array containing /// the bytes provided and a byte array containing the bytes read from process memory public static Tuple ByteCompare(ProcessInfo info, IntPtr startAddress, byte[] bytes) { byte[] memoryBytes = new byte[bytes.Length]; ErcCore.ReadProcessMemory(info.ProcessHandle, startAddress, bytes, bytes.Length, out int bytesRead); for(int i = 0; i < bytes.Length; i++) { if(bytes[i] != memoryBytes[i]) { return Tuple.Create(false, bytes, memoryBytes); } } return Tuple.Create(true, bytes, memoryBytes); } /// /// Compares a byte array with an area in memory of equal size. This method should be used in conjunction with the ByteArrayConstructor to identify /// bytes which can not be passed into a program without corrupting the input. /// /// The process to compare memory from /// The address at which to start the comparison /// The path to a file containing the bytes to be compared /// Returns a Tuple containing a bool which is true if the comparison was identical and false if it was not, a byte array containing /// the bytes provided and a byte array containing the bytes read from process memory public static Tuple ByteCompare(ProcessInfo info, IntPtr startAddress, string byteFilePath) { if (File.Exists(byteFilePath)) { byte[] bytes = File.ReadAllBytes(byteFilePath); byte[] memoryBytes = new byte[bytes.Length]; ErcCore.ReadProcessMemory(info.ProcessHandle, startAddress, bytes, bytes.Length, out int bytesRead); for (int i = 0; i < bytes.Length; i++) { if (bytes[i] != memoryBytes[i]) { return Tuple.Create(false, bytes, memoryBytes); } } return Tuple.Create(true, bytes, memoryBytes); } else { throw new FileNotFoundException(byteFilePath); } } #endregion } } ================================================ FILE: ERC/ERC/Process_Info.cs ================================================ using ERC.Structures; using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.IO; using System.Linq; using System.Net; using System.Runtime.InteropServices; using System.Text; using System.Text.RegularExpressions; namespace ERC { /// Contains information needed for the associated functions relating to the process. public class ProcessInfo : ErcCore { #region Class_Variables /// Name of the process. public string ProcessName { get; private set; } /// Process description. public string ProcessDescription { get; private set; } /// Path for the projects main module. public string ProcessPath { get; private set; } /// Process ID. public int ProcessID { get; private set; } /// Handle for the process. public IntPtr ProcessHandle { get; private set; } /// .Net Process object for this process public Process ProcessCurrent { get; private set; } /// The machine type the process runs on. Eg. x86 or x64 public MachineType ProcessMachineType { get; private set; } private Dictionary ProcessModuleHandles = new Dictionary(); /// A list containing ModuleInfo objects associuted with the process. /// public List ModulesInfo = new List(); /// A list containing ThreadInfo objects associuted with the process. /// public List ThreadsInfo = new List(); internal ErcCore ProcessCore; internal List ProcessMemoryBasicInfo32; internal List ProcessMemoryBasicInfo64; private const uint LIST_MODULES_ALL = 0x03; #endregion #region Constructor /// /// Constructor for the Process_Info object, requires an ERC_Core object and a Process. /// /// An ErcCore object /// The process to gather information from public ProcessInfo(ErcCore core, Process process) : base(core) { ProcessCore = core; if (Is64Bit(process)) { ProcessMachineType = MachineType.x64; } else { ProcessMachineType = MachineType.I386; } ProcessName = process.ProcessName; ProcessDescription = FileVersionInfo.GetVersionInfo(process.MainModule.FileName).FileDescription; ProcessPath = FileVersionInfo.GetVersionInfo(process.MainModule.FileName).FileName; ProcessID = process.Id; ProcessCurrent = process; ProcessHandle = process.Handle; ProcessModuleHandles = GetProcessModules().ReturnValue; if (ProcessModuleHandles.Count == 0) { for(int i = 0; i < process.Modules.Count; i++) { ProcessModuleHandles.Add(process.Modules[i].FileName, process.Modules[i].BaseAddress); } } foreach (KeyValuePair s in ProcessModuleHandles) { ModuleInfo thisModuleInfo = new ModuleInfo(s.Key, s.Value, process, core); if(thisModuleInfo.ModuleFailed == false) { ModulesInfo.Add(thisModuleInfo); } } for(int i = 0; i < process.Threads.Count; i++) { ThreadInfo thisThreadInfo = new ThreadInfo(process.Threads[i], ProcessCore, this); if(thisThreadInfo.ThreadFailed == false) { ThreadsInfo.Add(thisThreadInfo); } } LocateMemoryRegions(); } /// /// Constructor for the Process_Info object, requires an ERC_Core object and a Process. /// /// An ErcCore object /// The handle for the process to gather information from public ProcessInfo(ErcCore core, IntPtr handle) : base(core) { uint flags = 0; bool result = GetHandleInformation(handle, out flags); if(result == false) { throw new ERCException("The handle provided is not a valid process (GetHandleInformation returned false)"); } uint processID = GetProcessId(handle); Process process = Process.GetProcessById((int)processID); ProcessCore = core; if (Is64Bit(process)) { ProcessMachineType = MachineType.x64; } else { ProcessMachineType = MachineType.I386; } ProcessName = process.ProcessName; ProcessDescription = FileVersionInfo.GetVersionInfo(process.MainModule.FileName).FileDescription; ProcessPath = FileVersionInfo.GetVersionInfo(process.MainModule.FileName).FileName; ProcessID = process.Id; ProcessCurrent = process; ProcessHandle = process.Handle; ProcessModuleHandles = GetProcessModules().ReturnValue; if (ProcessModuleHandles.Count == 0) { for (int i = 0; i < process.Modules.Count; i++) { ProcessModuleHandles.Add(process.Modules[i].FileName, process.Modules[i].BaseAddress); } } foreach (KeyValuePair s in ProcessModuleHandles) { ModuleInfo thisModuleInfo = new ModuleInfo(s.Key, s.Value, process, core); if (thisModuleInfo.ModuleFailed == false) { ModulesInfo.Add(thisModuleInfo); } } for (int i = 0; i < process.Threads.Count; i++) { ThreadInfo thisThreadInfo = new ThreadInfo(process.Threads[i], ProcessCore, this); if (thisThreadInfo.ThreadFailed == false) { ThreadsInfo.Add(thisThreadInfo); } } LocateMemoryRegions(); } /// /// Constructor to use when inheriting from ProcessInfo. /// /// The object to inherit from protected ProcessInfo(ProcessInfo parent) { ProcessName = parent.ProcessName; ProcessDescription = parent.ProcessDescription; ProcessPath = parent.ProcessPath; ProcessID = parent.ProcessID; ProcessHandle = parent.ProcessHandle; ProcessCurrent = parent.ProcessCurrent; ProcessMachineType = parent.ProcessMachineType; ProcessModuleHandles = parent.ProcessModuleHandles; ModulesInfo = parent.ModulesInfo; ProcessCore = parent.ProcessCore; ProcessMemoryBasicInfo32 = parent.ProcessMemoryBasicInfo32; ProcessMemoryBasicInfo64 = parent.ProcessMemoryBasicInfo64; WorkingDirectory = parent.WorkingDirectory; Author = parent.Author; } #endregion #region ListLocalProcesses /// /// Gets a list of running processes on the host and removes unusable processes (such as system processes etc) /// /// An ErcCore object /// Returns an ErcResult containing a list of all supported processes public static ErcResult ListLocalProcesses(ErcCore core) { ErcResult result = new ErcResult(core); Process[] processes = Process.GetProcesses(); List processesToRemove = new List(); for(int i = 0; i < processes.Length; i++) { string filename = null; try { filename = processes[i].MainModule.FileName; } catch(Exception) { processesToRemove.Add(i); } } Process[] usableProcesses = new Process[processes.Length - processesToRemove.Count]; int processCounter = 0; for (int i = 0; i < processes.Length; i++) { if (!processesToRemove.Contains(i)) { usableProcesses[processCounter] = processes[i]; processCounter++; } } result.ReturnValue = usableProcesses; return result; } #endregion #region ListRemoteProcesses /// /// Gets a list of running processes on the host and removes unusable processes. /// /// An ErcCore object /// The computer from which to read the list of processes. Can be either the hostname or IP address. /// Returns an ErcResult containing a list of all supported processes public static ErcResult ListRemoteProcesses(ErcCore core, string machineName) { ErcResult result = new ErcResult(core); IPAddress machine = null; if(IPAddress.TryParse(machineName, out machine)) { IPHostEntry hostEntry = Dns.GetHostEntry(machine); machineName = hostEntry.HostName; } Process[] processes = Process.GetProcesses(machineName); List processesToRemove = new List(); for (int i = 0; i < processes.Length; i++) { string filename = null; try { filename = processes[i].MainModule.FileName; } catch (Exception) { processesToRemove.Add(i); } } Process[] usableProcesses = new Process[processes.Length - processesToRemove.Count]; int processCounter = 0; for (int i = 0; i < processes.Length; i++) { if (!processesToRemove.Contains(i)) { usableProcesses[processCounter] = processes[i]; processCounter++; } } result.ReturnValue = usableProcesses; return result; } #endregion #region GetProcessModules /// /// Returns a list of files loaded by the current process as List String /// /// Returns an ErcResult containing a Dictionary of module names and the associated handles public ErcResult> GetProcessModules() { IntPtr hProcess = ProcessHandle; ErcResult> result = new ErcResult>(ProcessCore); result.ReturnValue = new Dictionary(); Dictionary modules = new Dictionary(); if (hProcess != IntPtr.Zero) { try { IntPtr[] modhWnds = new IntPtr[0]; int lpcbNeeded = 0; try { // -- call EnumProcessModules the first time to get the size of the array needed EnumProcessModulesEx(hProcess, modhWnds, 0, out lpcbNeeded, LIST_MODULES_ALL); modhWnds = new IntPtr[lpcbNeeded / IntPtr.Size]; EnumProcessModulesEx(hProcess, modhWnds, modhWnds.Length * IntPtr.Size, out lpcbNeeded, LIST_MODULES_ALL); } catch { result.ReturnValue = modules; return result; } for (int i = 0; i < modhWnds.Length; i++) { StringBuilder modName = new StringBuilder(256); if (GetModuleFileNameEx(hProcess, modhWnds[i], modName, modName.Capacity) != 0) { if (!modules.ContainsKey(modName.ToString())) { modules.Add(modName.ToString(), modhWnds[i]); } } } } catch (Exception e) { result.Error = e; result.LogEvent(); return result; } } result.ReturnValue = modules; return result; } #endregion #region Identify_Process_Architecture /// /// Identifies if a process is 64bit or 32 bit, returns true for 64bit and false for 32bit. /// /// The process to be used /// Returns true if the process is 64bit and false if it is not. public static bool Is64Bit(Process process) { bool isWow64; if(process == null) { throw new ERCException("No process attached."); } if (!Environment.Is64BitOperatingSystem) { return false; } if (!IsWow64Process(process.Handle, out isWow64)) { throw new ERCException("An error has occured in the IsWow64Process call from Process.Is64Bit()"); } return !isWow64; } #endregion #region LocateMemoryRegions /// /// Identifies memory regions occupied by the current process and populates the associated list with the Process_Info object. /// private void LocateMemoryRegions() { Process process = ProcessCurrent; if (ProcessMachineType == MachineType.I386) { ProcessMemoryBasicInfo32 = new List(); long MaxAddress = 0x7fffffff; long address = 0; long oldAddress = 0; do { MEMORY_BASIC_INFORMATION32 m; int result = VirtualQueryEx32(process.Handle, (IntPtr)address, out m, (uint)Marshal.SizeOf(typeof(MEMORY_BASIC_INFORMATION32))); if (address == (long)m.BaseAddress + (long)m.RegionSize) break; address = (long)m.BaseAddress + (long)m.RegionSize; if (oldAddress > address) { address = long.MaxValue; } oldAddress = address; if (m.State == StateEnum.MEM_COMMIT && (m.Type == TypeEnum.MEM_MAPPED || m.Type == TypeEnum.MEM_PRIVATE)) { ProcessMemoryBasicInfo32.Add(m); } } while (address <= MaxAddress); } else if (ProcessMachineType == MachineType.x64) { ProcessMemoryBasicInfo64 = new List(); long MaxAddress = 0x000007FFFFFEFFFF; long address = 0; long oldAddress = 0; do { MEMORY_BASIC_INFORMATION64 m; int result = VirtualQueryEx64(process.Handle, (IntPtr)address, out m, (uint)Marshal.SizeOf(typeof(MEMORY_BASIC_INFORMATION64))); if (address == (long)m.BaseAddress + (long)m.RegionSize) break; address = (long)m.BaseAddress + (long)m.RegionSize; if (oldAddress > address) { address = long.MaxValue; } oldAddress = address; if (m.State == StateEnum.MEM_COMMIT && (m.Type == TypeEnum.MEM_MAPPED || m.Type == TypeEnum.MEM_PRIVATE)) { ProcessMemoryBasicInfo64.Add(m); } } while (address <= MaxAddress); } else { throw new ERCException("Machine type is invalid"); } } #endregion #region Search_Functions #region Search_Process_Memory /// /// Private function called from Search_Memory. Searches memory regions populated by the process for specific patterns. /// /// Takes a byte array as input to be searched for /// Returns a list of IntPtr for each instance found. internal ErcResult> SearchProcessMemory(byte[] searchBytes) { ErcResult> resultAddresses = new ErcResult>(ProcessCore); resultAddresses.ReturnValue = new List(); Process process = ProcessCurrent; if (ProcessMachineType == MachineType.I386) { for (int i = 0; i < ProcessMemoryBasicInfo32.Count; i++) { if((ulong)ProcessMemoryBasicInfo32[i].RegionSize > int.MaxValue) { long startAddress = (long)ProcessMemoryBasicInfo32[i].BaseAddress; long endAddress = (long)ProcessMemoryBasicInfo32[i].BaseAddress + (long)(ProcessMemoryBasicInfo32[i].RegionSize - 1); long region = (long)ProcessMemoryBasicInfo32[i].RegionSize; for (long j = startAddress; j < endAddress; j += (region / 100)) { byte[] buffer = new byte[region / 100]; int bytesRead = 0; ReadProcessMemory(ProcessHandle, (IntPtr)j, buffer, buffer.Length, out bytesRead); long pos = 0; long index = 0; do { byte[] buffer1Partial = new byte[buffer.Length - pos]; Array.Copy(buffer, pos, buffer1Partial, 0, buffer.Length - pos); index = ByteIndexOf(buffer1Partial, searchBytes); if (index != -1) { resultAddresses.ReturnValue.Add((IntPtr)(index + (long)ProcessMemoryBasicInfo32[i].BaseAddress + pos)); } pos += index; if (index == 0) { pos += searchBytes.Length; index = 1; } } while (index != -1 && index != 0); } } else { long bufferSize = (long)ProcessMemoryBasicInfo32[i].RegionSize; int bytesRead = 0; IntPtr baseAddress = ProcessMemoryBasicInfo32[i].BaseAddress; byte[] buffer = new byte[bufferSize]; ReadProcessMemory(ProcessHandle, baseAddress, buffer, buffer.Length, out bytesRead); long pos = 0; long index = 0; do { byte[] buffer1Partial = new byte[buffer.Length - pos]; Array.Copy(buffer, pos, buffer1Partial, 0, buffer.Length - pos); index = ByteIndexOf(buffer1Partial, searchBytes); if (index != -1) { resultAddresses.ReturnValue.Add((IntPtr)(index + (long)ProcessMemoryBasicInfo32[i].BaseAddress + pos)); } pos += index; if (index == 0) { pos += searchBytes.Length; index = 1; } } while (index != -1 && index != 0); } } } else if(ProcessMachineType == MachineType.x64) { byte[] buffer = new byte[int.MaxValue / 10]; int bytesRead = 0; for (int i = 0; i < ProcessMemoryBasicInfo64.Count; i++) { if (ProcessMemoryBasicInfo64[i].RegionSize > int.MaxValue) { ulong startAddress = ProcessMemoryBasicInfo64[i].BaseAddress; ulong endAddress = ProcessMemoryBasicInfo64[i].BaseAddress + (ProcessMemoryBasicInfo64[i].RegionSize - 1); ulong region = ProcessMemoryBasicInfo64[i].RegionSize; for (ulong j = startAddress; j < endAddress; j += int.MaxValue / 10) { ReadProcessMemory(ProcessHandle, (IntPtr)j, buffer, buffer.Length, out bytesRead); long pos = 0; long index = 0; do { byte[] buffer1Partial = new byte[buffer.Length - pos]; Array.Copy(buffer, pos, buffer1Partial, 0, buffer.Length - pos); index = ByteIndexOf(buffer1Partial, searchBytes); if (index != -1) { resultAddresses.ReturnValue.Add((IntPtr)(index + (long)ProcessMemoryBasicInfo64[i].BaseAddress + pos)); } pos += index; if (index == 0) { pos += searchBytes.Length; index = 1; } } while (index != -1 && index != 0); } } else { long bufferSize = (long)ProcessMemoryBasicInfo64[i].RegionSize; bytesRead = 0; IntPtr baseAddress = (IntPtr)ProcessMemoryBasicInfo64[i].BaseAddress; byte[] buffer1 = new byte[bufferSize]; ReadProcessMemory(ProcessHandle, baseAddress, buffer1, buffer1.Length, out bytesRead); long pos = 0; long index = 0; do { byte[] buffer1Partial = new byte[buffer1.Length - pos]; Array.Copy(buffer1, pos, buffer1Partial, 0, buffer1.Length - pos); index = ByteIndexOf(buffer1Partial, searchBytes); if (index != -1) { resultAddresses.ReturnValue.Add((IntPtr)(index + (long)ProcessMemoryBasicInfo64[i].BaseAddress + pos)); } pos += index; if(index == 0) { pos += searchBytes.Length; index = 1; } } while (index != -1 && index != 0); } } } resultAddresses.ReturnValue = new HashSet(resultAddresses.ReturnValue).ToList(); return resultAddresses; } /// /// Private function called from Search_Memory. Searches memory regions populated by the process for specific strings. /// /// Takes a byte array as input to be searched for /// Takes a byte array of values used to disqualify pointers /// Returns a list of IntPtr for each instance found. internal ErcResult> SearchProcessMemory(byte[] searchBytes, byte[] ptrsToExclude) { ErcResult> resultAddresses = new ErcResult>(ProcessCore); resultAddresses.ReturnValue = new List(); Process process = ProcessCurrent; if (ProcessMachineType == MachineType.I386) { for (int i = 0; i < ProcessMemoryBasicInfo32.Count; i++) { if ((ulong)ProcessMemoryBasicInfo32[i].RegionSize > int.MaxValue) { long startAddress = (long)ProcessMemoryBasicInfo32[i].BaseAddress; long endAddress = (long)ProcessMemoryBasicInfo32[i].BaseAddress + (long)(ProcessMemoryBasicInfo32[i].RegionSize - 1); long region = (long)ProcessMemoryBasicInfo32[i].RegionSize; for (long j = startAddress; j < endAddress; j += (region / 100)) { byte[] buffer = new byte[region / 100]; int bytesRead = 0; ReadProcessMemory(ProcessHandle, (IntPtr)j, buffer, buffer.Length, out bytesRead); long pos = 0; long index = 0; do { byte[] buffer1Partial = new byte[buffer.Length - pos]; Array.Copy(buffer, pos, buffer1Partial, 0, buffer.Length - pos); index = ByteIndexOf(buffer1Partial, searchBytes); if (index != -1) { resultAddresses.ReturnValue.Add((IntPtr)(index + (long)ProcessMemoryBasicInfo32[i].BaseAddress + pos)); } pos += index; if (index == 0) { pos += searchBytes.Length; index = 1; } } while (index != -1 && index != 0); } } else { long bufferSize = (long)ProcessMemoryBasicInfo32[i].RegionSize; int bytesRead = 0; IntPtr baseAddress = ProcessMemoryBasicInfo32[i].BaseAddress; byte[] buffer = new byte[bufferSize]; ReadProcessMemory(ProcessHandle, baseAddress, buffer, buffer.Length, out bytesRead); long pos = 0; long index = 0; do { byte[] buffer1Partial = new byte[buffer.Length - pos]; Array.Copy(buffer, pos, buffer1Partial, 0, buffer.Length - pos); index = ByteIndexOf(buffer1Partial, searchBytes); if (index != -1) { resultAddresses.ReturnValue.Add((IntPtr)(index + (long)ProcessMemoryBasicInfo32[i].BaseAddress + pos)); } pos += index; if (index == 0) { pos += searchBytes.Length; index = 1; } } while (index != -1 && index != 0); } } } else if (ProcessMachineType == MachineType.x64) { byte[] buffer = new byte[int.MaxValue / 10]; int bytesRead = 0; for (int i = 0; i < ProcessMemoryBasicInfo64.Count; i++) { if (ProcessMemoryBasicInfo64[i].RegionSize > int.MaxValue) { ulong startAddress = ProcessMemoryBasicInfo64[i].BaseAddress; ulong endAddress = ProcessMemoryBasicInfo64[i].BaseAddress + (ProcessMemoryBasicInfo64[i].RegionSize - 1); ulong region = ProcessMemoryBasicInfo64[i].RegionSize; for (ulong j = startAddress; j < endAddress; j += int.MaxValue / 10) { ReadProcessMemory(ProcessHandle, (IntPtr)j, buffer, buffer.Length, out bytesRead); long pos = 0; long index = 0; do { byte[] buffer1Partial = new byte[buffer.Length - pos]; Array.Copy(buffer, pos, buffer1Partial, 0, buffer.Length - pos); index = ByteIndexOf(buffer1Partial, searchBytes); if (index != -1) { resultAddresses.ReturnValue.Add((IntPtr)(index + (long)ProcessMemoryBasicInfo64[i].BaseAddress + pos)); } pos += index; if (index == 0) { pos += searchBytes.Length; index = 1; } } while (index != -1 && index != 0); } } else { long bufferSize = (long)ProcessMemoryBasicInfo64[i].RegionSize; bytesRead = 0; IntPtr baseAddress = (IntPtr)ProcessMemoryBasicInfo64[i].BaseAddress; byte[] buffer1 = new byte[bufferSize]; ReadProcessMemory(ProcessHandle, baseAddress, buffer1, buffer1.Length, out bytesRead); long pos = 0; long index = 0; do { byte[] buffer1Partial = new byte[buffer1.Length - pos]; Array.Copy(buffer1, pos, buffer1Partial, 0, buffer1.Length - pos); index = ByteIndexOf(buffer1Partial, searchBytes); if (index != -1) { resultAddresses.ReturnValue.Add((IntPtr)(index + (long)ProcessMemoryBasicInfo64[i].BaseAddress + pos)); } pos += index; if (index == 0) { pos += searchBytes.Length; index = 1; } } while (index != -1 && index != 0); } } } resultAddresses.ReturnValue = new HashSet(resultAddresses.ReturnValue).ToList(); resultAddresses.ReturnValue = Utilities.PtrRemover.RemovePointers(ProcessMachineType, resultAddresses.ReturnValue, ptrsToExclude); return resultAddresses; } #endregion #region SearchAllMemoryPPR /// /// Searches all memory associated with a given process and associated modules for POP X POP X RET instructions. /// Passing a list of module paths or names will exclude those modules from the search. /// /// Takes a list of module names to be excluded from the search /// Returns an ERC_Result containing a dictionary of pointers and the main module in which they were found public ErcResult> SearchAllMemoryPPR(List excludes = null) { ErcResult> ptrs = new ErcResult>(ProcessCore); ptrs.ReturnValue = new Dictionary(); if (ProcessMachineType == MachineType.I386) { for (int i = 0; i < ProcessMemoryBasicInfo32.Count; i++) { if ((ulong)ProcessMemoryBasicInfo32[i].RegionSize > int.MaxValue) { long start_address = (long)ProcessMemoryBasicInfo32[i].BaseAddress; long end_address = (long)ProcessMemoryBasicInfo32[i].BaseAddress + (long)(ProcessMemoryBasicInfo32[i].RegionSize - 1); long region = (long)ProcessMemoryBasicInfo32[i].RegionSize; for (long j = start_address; j < end_address; j += (region / 100)) { byte[] buffer = new byte[region / 100]; int bytesRead = 0; ReadProcessMemory(ProcessHandle, (IntPtr)j, buffer, buffer.Length, out bytesRead); List pprs = ERC.Utilities.Payloads.PopPopRet(buffer); if (pprs.Count > 0) { for (int k = 0; k < pprs.Count; k++) { if (!ptrs.ReturnValue.ContainsKey((IntPtr)((ulong)pprs[k] + (ulong)ProcessMemoryBasicInfo32[i].BaseAddress))) { ptrs.ReturnValue.Add((IntPtr)((ulong)pprs[k] + (ulong)ProcessMemoryBasicInfo32[i].BaseAddress), ProcessPath); } } } } } else { long bufferSize = (long)ProcessMemoryBasicInfo32[i].RegionSize; int bytesRead = 0; IntPtr baseAddress = ProcessMemoryBasicInfo32[i].BaseAddress; byte[] buffer = new byte[bufferSize]; ReadProcessMemory(ProcessHandle, baseAddress, buffer, buffer.Length, out bytesRead); List pprs = ERC.Utilities.Payloads.PopPopRet(buffer); if (pprs.Count > 0) { for (int k = 0; k < pprs.Count; k++) { if (!ptrs.ReturnValue.ContainsKey((IntPtr)((ulong)pprs[k] + (ulong)ProcessMemoryBasicInfo32[i].BaseAddress))) { ptrs.ReturnValue.Add((IntPtr)((ulong)pprs[k] + (ulong)ProcessMemoryBasicInfo32[i].BaseAddress), ProcessPath); } } } } } } else if (ProcessMachineType == MachineType.x64) { byte[] buffer = new byte[int.MaxValue / 10]; int bytesRead = 0; for (int i = 0; i < ProcessMemoryBasicInfo64.Count; i++) { if (ProcessMemoryBasicInfo64[i].RegionSize > int.MaxValue) { ulong startAddress = ProcessMemoryBasicInfo64[i].BaseAddress; ulong endAddress = ProcessMemoryBasicInfo64[i].BaseAddress + (ProcessMemoryBasicInfo64[i].RegionSize - 1); ulong region = ProcessMemoryBasicInfo64[i].RegionSize; for (ulong j = startAddress; j < endAddress; j += int.MaxValue / 10) { ReadProcessMemory(ProcessHandle, (IntPtr)j, buffer, buffer.Length, out bytesRead); List pprs = ERC.Utilities.Payloads.PopPopRet(buffer); if (pprs.Count > 0) { for (int k = 0; k < pprs.Count; k++) { if (!ptrs.ReturnValue.ContainsKey((IntPtr)((ulong)pprs[k] + ProcessMemoryBasicInfo64[i].BaseAddress))) { ptrs.ReturnValue.Add((IntPtr)((ulong)pprs[k] + ProcessMemoryBasicInfo64[i].BaseAddress), ProcessPath); } } } } } else { long bufferSize = (long)ProcessMemoryBasicInfo64[i].RegionSize; bytesRead = 0; IntPtr baseAddress = (IntPtr)ProcessMemoryBasicInfo64[i].BaseAddress; byte[] buffer1 = new byte[bufferSize]; ReadProcessMemory(ProcessHandle, baseAddress, buffer1, buffer1.Length, out bytesRead); List pprs = ERC.Utilities.Payloads.PopPopRet(buffer1); if(pprs.Count > 0) { for (int k = 0; k < pprs.Count; k++) { if (!ptrs.ReturnValue.ContainsKey((IntPtr)((ulong)pprs[k] + ProcessMemoryBasicInfo64[i].BaseAddress))) { ptrs.ReturnValue.Add((IntPtr)((ulong)pprs[k] + ProcessMemoryBasicInfo64[i].BaseAddress), ProcessPath); } } } } } } List modules = new List(); for(int i = 0; i < ModulesInfo.Count; i++) { if (excludes != null) { if (!excludes.Contains(ModulesInfo[i].ModuleName) && !excludes.Contains(ModulesInfo[i].ModulePath)) { modules.Add(ModulesInfo[i]); } } else { modules.Add(ModulesInfo[i]); } } for(int i = 0; i < modules.Count; i++) { IntPtr baseAddress = modules[i].ModuleBase; byte[] buffer = new byte[modules[i].ModuleSize]; int bytesread = 0; ReadProcessMemory(ProcessHandle, modules[i].ModuleBase, buffer, buffer.Length, out bytesread); List pprs = ERC.Utilities.Payloads.PopPopRet(buffer); if (pprs.Count > 0) { for (int k = 0; k < pprs.Count; k++) { if (!ptrs.ReturnValue.ContainsKey((IntPtr)((ulong)pprs[k] + (ulong)modules[i].ModuleBase))) { ptrs.ReturnValue.Add((IntPtr)((ulong)pprs[k] + (ulong)modules[i].ModuleBase), modules[i].ModulePath); } } } } return ptrs; } /// /// Searches all memory associated with a given process and associated modules for POP X POP X RET instructions. /// Passing a list of module paths or names will exclude those modules from the search. /// /// Takes a list of module names to be excluded from the search /// Takes a byte array of values used to disqualify pointers /// Returns an ERC_Result containing a dictionary of pointers and the main module in which they were found public ErcResult> SearchAllMemoryPPR(byte[] ptrsToExclude, List excludes = null) { ErcResult> ptrs = new ErcResult>(ProcessCore); ptrs.ReturnValue = new Dictionary(); if (ProcessMachineType == MachineType.I386) { for (int i = 0; i < ProcessMemoryBasicInfo32.Count; i++) { if ((ulong)ProcessMemoryBasicInfo32[i].RegionSize > int.MaxValue) { long start_address = (long)ProcessMemoryBasicInfo32[i].BaseAddress; long end_address = (long)ProcessMemoryBasicInfo32[i].BaseAddress + (long)(ProcessMemoryBasicInfo32[i].RegionSize - 1); long region = (long)ProcessMemoryBasicInfo32[i].RegionSize; for (long j = start_address; j < end_address; j += (region / 100)) { byte[] buffer = new byte[region / 100]; int bytesRead = 0; ReadProcessMemory(ProcessHandle, (IntPtr)j, buffer, buffer.Length, out bytesRead); List pprs = ERC.Utilities.Payloads.PopPopRet(buffer); if (pprs.Count > 0) { for (int k = 0; k < pprs.Count; k++) { if (!ptrs.ReturnValue.ContainsKey((IntPtr)((ulong)pprs[k] + (ulong)ProcessMemoryBasicInfo32[i].BaseAddress))) { ptrs.ReturnValue.Add((IntPtr)((ulong)pprs[k] + (ulong)ProcessMemoryBasicInfo32[i].BaseAddress), ProcessPath); } } } } } else { long bufferSize = (long)ProcessMemoryBasicInfo32[i].RegionSize; int bytesRead = 0; IntPtr baseAddress = ProcessMemoryBasicInfo32[i].BaseAddress; byte[] buffer = new byte[bufferSize]; ReadProcessMemory(ProcessHandle, baseAddress, buffer, buffer.Length, out bytesRead); List pprs = ERC.Utilities.Payloads.PopPopRet(buffer); if (pprs.Count > 0) { for (int k = 0; k < pprs.Count; k++) { if (!ptrs.ReturnValue.ContainsKey((IntPtr)((ulong)pprs[k] + (ulong)ProcessMemoryBasicInfo32[i].BaseAddress))) { ptrs.ReturnValue.Add((IntPtr)((ulong)pprs[k] + (ulong)ProcessMemoryBasicInfo32[i].BaseAddress), ProcessPath); } } } } } } else if (ProcessMachineType == MachineType.x64) { byte[] buffer = new byte[int.MaxValue / 10]; int bytesRead = 0; for (int i = 0; i < ProcessMemoryBasicInfo64.Count; i++) { if (ProcessMemoryBasicInfo64[i].RegionSize > int.MaxValue) { ulong startAddress = ProcessMemoryBasicInfo64[i].BaseAddress; ulong endAddress = ProcessMemoryBasicInfo64[i].BaseAddress + (ProcessMemoryBasicInfo64[i].RegionSize - 1); ulong region = ProcessMemoryBasicInfo64[i].RegionSize; for (ulong j = startAddress; j < endAddress; j += int.MaxValue / 10) { ReadProcessMemory(ProcessHandle, (IntPtr)j, buffer, buffer.Length, out bytesRead); List pprs = ERC.Utilities.Payloads.PopPopRet(buffer); if (pprs.Count > 0) { for (int k = 0; k < pprs.Count; k++) { if (!ptrs.ReturnValue.ContainsKey((IntPtr)((ulong)pprs[k] + ProcessMemoryBasicInfo64[i].BaseAddress))) { ptrs.ReturnValue.Add((IntPtr)((ulong)pprs[k] + ProcessMemoryBasicInfo64[i].BaseAddress), ProcessPath); } } } } } else { long bufferSize = (long)ProcessMemoryBasicInfo64[i].RegionSize; bytesRead = 0; IntPtr baseAddress = (IntPtr)ProcessMemoryBasicInfo64[i].BaseAddress; byte[] buffer1 = new byte[bufferSize]; ReadProcessMemory(ProcessHandle, baseAddress, buffer1, buffer1.Length, out bytesRead); List pprs = ERC.Utilities.Payloads.PopPopRet(buffer1); if (pprs.Count > 0) { for (int k = 0; k < pprs.Count; k++) { if (!ptrs.ReturnValue.ContainsKey((IntPtr)((ulong)pprs[k] + ProcessMemoryBasicInfo64[i].BaseAddress))) { ptrs.ReturnValue.Add((IntPtr)((ulong)pprs[k] + ProcessMemoryBasicInfo64[i].BaseAddress), ProcessPath); } } } } } } List modules = new List(); for (int i = 0; i < ModulesInfo.Count; i++) { if (excludes != null) { if (!excludes.Contains(ModulesInfo[i].ModuleName) && !excludes.Contains(ModulesInfo[i].ModulePath)) { modules.Add(ModulesInfo[i]); } } else { modules.Add(ModulesInfo[i]); } } for (int i = 0; i < modules.Count; i++) { IntPtr baseAddress = modules[i].ModuleBase; byte[] buffer = new byte[modules[i].ModuleSize]; int bytesread = 0; ReadProcessMemory(ProcessHandle, modules[i].ModuleBase, buffer, buffer.Length, out bytesread); List pprs = ERC.Utilities.Payloads.PopPopRet(buffer); if (pprs.Count > 0) { for (int k = 0; k < pprs.Count; k++) { if (!ptrs.ReturnValue.ContainsKey((IntPtr)((ulong)pprs[k] + (ulong)modules[i].ModuleBase))) { ptrs.ReturnValue.Add((IntPtr)((ulong)pprs[k] + (ulong)modules[i].ModuleBase), modules[i].ModulePath); } } } } ptrs.ReturnValue = Utilities.PtrRemover.RemovePointers(ProcessMachineType, ptrs.ReturnValue, ptrsToExclude); return ptrs; } #endregion #region SearchMemory /// /// Searches all memory (the process and associated DLLs) for a specific string or byte array. Strings can be passed as ASCII, Unicode, UTF7 or UTF8. /// Specific modules can be exclude through passing a Listof strings containing module names or paths. /// /// 0 = search term is in bytes\n1 = search term is in unicode\n2 = search term is in ASCII\n3 = Search term is in UTF8\n4 = Search term is in UTF7\n5 = Search term is in UTF32 /// Byte array to be searched for (optional) /// String to be searched for (optional) /// Modules to be excluded from the search (optional) /// Returns an ERC_Result containing pointers to all instances of the search query. public ErcResult> SearchMemory(int searchType, byte[] searchBytes = null, string searchString = null, List excludes = null) { ErcResult> resultAddresses = new ErcResult>(ProcessCore); if (searchBytes == null && searchString == null) { resultAddresses.Error = new ERCException("No search term provided. " + "Either a byte array or string must be provided as the search term or there is nothing to search for."); resultAddresses.LogEvent(); return resultAddresses; } resultAddresses.ReturnValue = new Dictionary(); switch (searchType) { case 0: break; case 1: searchBytes = Encoding.Unicode.GetBytes(searchString); break; case 2: searchBytes = Encoding.ASCII.GetBytes(searchString); break; case 3: searchBytes = Encoding.UTF8.GetBytes(searchString); break; case 4: searchBytes = Encoding.UTF7.GetBytes(searchString); break; case 5: searchBytes = Encoding.UTF32.GetBytes(searchString); break; default: resultAddresses.Error = new ERCException("Incorrect searchType value provided, value must be 0-4"); resultAddresses.LogEvent(); return resultAddresses; } var processPtrs = SearchProcessMemory(searchBytes); if(processPtrs.Error != null) { resultAddresses.Error = new ERCException("Error passed from Search_Process_Memory: " + processPtrs.Error.ToString()); resultAddresses.LogEvent(); return resultAddresses; } for(int i = 0; i < processPtrs.ReturnValue.Count; i++) { if (!resultAddresses.ReturnValue.ContainsKey(processPtrs.ReturnValue[i])) { resultAddresses.ReturnValue.Add(processPtrs.ReturnValue[i], ProcessPath); } } List modules = new List(); for (int i = 0; i < ModulesInfo.Count; i++) { if (excludes != null) { if (!excludes.Contains(ModulesInfo[i].ModuleName) && !excludes.Contains(ModulesInfo[i].ModulePath)) { modules.Add(ModulesInfo[i]); } } else { modules.Add(ModulesInfo[i]); } } for(int i = 0; i < modules.Count; i++) { var modulePtrs = modules[i].SearchModule(searchBytes); if(modulePtrs.ReturnValue.Count > 0) { for(int j = 0; j < modulePtrs.ReturnValue.Count; j++) { if (!resultAddresses.ReturnValue.ContainsKey(modulePtrs.ReturnValue[j])) { resultAddresses.ReturnValue.Add(modulePtrs.ReturnValue[j], modules[i].ModulePath); } } } } return resultAddresses; } /// /// Searches all memory (the process and associated DLLs) for a specific string or byte array. Strings can be passed as ASCII, Unicode, UTF7 or UTF8. /// Specific modules can be exclude through passing a Listof strings containing module names or paths. /// /// 0 = search term is in bytes\n1 = search term is in unicode\n2 = search term is in ASCII\n3 = Search term is in UTF8\n4 = Search term is in UTF7\n5 = Search term is in UTF32 /// Takes a byte array of values used to disqualify pointers /// Byte array to be searched for (optional) /// String to be searched for (optional) /// Modules to be excluded from the search (optional) /// Returns an ERC_Result containing pointers to all instances of the search query. public ErcResult> SearchMemory(int searchType, byte[] ptrsToExclude, byte[] searchBytes = null, string searchString = null, List excludes = null) { ErcResult> resultAddresses = new ErcResult>(ProcessCore); if (searchBytes == null && searchString == null) { resultAddresses.Error = new ERCException("No search term provided. " + "Either a byte array or string must be provided as the search term or there is nothing to search for."); resultAddresses.LogEvent(); return resultAddresses; } resultAddresses.ReturnValue = new Dictionary(); switch (searchType) { case 0: break; case 1: searchBytes = Encoding.Unicode.GetBytes(searchString); break; case 2: searchBytes = Encoding.ASCII.GetBytes(searchString); break; case 3: searchBytes = Encoding.UTF8.GetBytes(searchString); break; case 4: searchBytes = Encoding.UTF7.GetBytes(searchString); break; case 5: searchBytes = Encoding.UTF32.GetBytes(searchString); break; default: resultAddresses.Error = new ERCException("Incorrect searchType value provided, value must be 0-4"); resultAddresses.LogEvent(); return resultAddresses; } var processPtrs = SearchProcessMemory(searchBytes); if (processPtrs.Error != null) { resultAddresses.Error = new ERCException("Error passed from Search_Process_Memory: " + processPtrs.Error.ToString()); resultAddresses.LogEvent(); return resultAddresses; } for (int i = 0; i < processPtrs.ReturnValue.Count; i++) { if (!resultAddresses.ReturnValue.ContainsKey(processPtrs.ReturnValue[i])) { resultAddresses.ReturnValue.Add(processPtrs.ReturnValue[i], ProcessPath); } } List modules = new List(); for (int i = 0; i < ModulesInfo.Count; i++) { if (excludes != null) { if (!excludes.Contains(ModulesInfo[i].ModuleName) && !excludes.Contains(ModulesInfo[i].ModulePath)) { modules.Add(ModulesInfo[i]); } } else { modules.Add(ModulesInfo[i]); } } for (int i = 0; i < modules.Count; i++) { var modulePtrs = modules[i].SearchModule(searchBytes); if (modulePtrs.ReturnValue.Count > 0) { for (int j = 0; j < modulePtrs.ReturnValue.Count; j++) { if (!resultAddresses.ReturnValue.ContainsKey(modulePtrs.ReturnValue[j])) { resultAddresses.ReturnValue.Add(modulePtrs.ReturnValue[j], modules[i].ModulePath); } } } } resultAddresses.ReturnValue = Utilities.PtrRemover.RemovePointers(ProcessMachineType, resultAddresses.ReturnValue, ptrsToExclude); return resultAddresses; } #endregion #region SearchModules /// /// Searches all modules loaded by a process for a specific string or byte array. Strings can be passed as ASCII, Unicode, UTF7 or UTF8. /// Search can be limited to specific modules through passing a List of strings containing module names or paths. /// /// 0 = search term is in bytes\n1 = search term is in unicode\n2 = search term is in ASCII\n3 = Search term is in UTF8\n4 = Search term is in UTF7\n5 = Search term is in UTF32 /// Takes a byte array of values used to disqualify pointers /// Byte array to be searched for (optional) /// String to be searched for (optional) /// Modules to be included in the search (optional) /// Modules to be excluded from the search (optional) /// Returns an ERC_Result containing pointers to all instances of the search query.> public ErcResult> SearchModules(int searchType, byte[] ptrsToExclude = null, byte[] searchBytes = null, string searchString = null, List includedModules = null, List excludedModules = null) { ErcResult> resultAddresses = new ErcResult>(ProcessCore); if (searchBytes == null && searchString == null) { resultAddresses.Error = new ERCException("No search term provided. " + "Either a byte array or string must be provided as the search term or there is nothing to search for."); resultAddresses.LogEvent(); return resultAddresses; } resultAddresses.ReturnValue = new Dictionary(); switch (searchType) { case 0: break; case 1: searchBytes = Encoding.Unicode.GetBytes(searchString); break; case 2: searchBytes = Encoding.ASCII.GetBytes(searchString); break; case 3: searchBytes = Encoding.UTF8.GetBytes(searchString); break; case 4: searchBytes = Encoding.UTF7.GetBytes(searchString); break; case 5: searchBytes = Encoding.UTF32.GetBytes(searchString); break; default: resultAddresses.Error = new ERCException("Incorrect searchType value provided, value must be 0-4"); resultAddresses.LogEvent(); return resultAddresses; } List modules = new List(); for (int i = 0; i < ModulesInfo.Count; i++) { if (includedModules != null) { if (includedModules.Contains(ModulesInfo[i].ModuleName) || includedModules.Contains(ModulesInfo[i].ModulePath)) { if(excludedModules != null) { if(!excludedModules.Contains(ModulesInfo[i].ModuleName) && !excludedModules.Contains(ModulesInfo[i].ModulePath)) { modules.Add(ModulesInfo[i]); } } } } else { modules.Add(ModulesInfo[i]); } } for (int i = 0; i < modules.Count; i++) { var modulePtrs = modules[i].SearchModule(searchBytes); if (modulePtrs.ReturnValue.Count > 0) { for (int j = 0; j < modulePtrs.ReturnValue.Count; j++) { if (!resultAddresses.ReturnValue.ContainsKey(modulePtrs.ReturnValue[j])) { resultAddresses.ReturnValue.Add(modulePtrs.ReturnValue[j], modules[i].ModulePath); } } } } if(ptrsToExclude != null) { resultAddresses.ReturnValue = Utilities.PtrRemover.RemovePointers(ProcessMachineType, resultAddresses.ReturnValue, ptrsToExclude); } return resultAddresses; } #endregion #region FindNRP /// /// Searches process registers and identifies pointers to buffers in memory containing a non repeating pattern. Functionality to identify SEH overwrites not yet implements. /// /// (Optional) 0 = search term is system default\n1 = search term is in unicode\n2 = search term is in ASCII\n3 = Search term is in UTF8\n4 = Search term is in UTF7\n5 = Search term is in UTF32 /// (Optional) Include additional characters in the pattern (!#$%^ etc) in the to be searched /// Returns a ERC_Result containing a List of RegisterOffset public ErcResult> FindNRP(int searchType = 0, bool extended = false) { ErcResult> offsets = new ErcResult>(ProcessCore); List nrps = new List(); string pattern = ""; if(extended == false) { pattern = File.ReadAllText(ProcessCore.PatternStandardPath); } else { pattern = File.ReadAllText(ProcessCore.PatternExtendedPath); } string nrpHolder = ""; int counter = 0; for(int i = 0; i < pattern.Length; i++) { if(counter != 2) { nrpHolder += pattern[i]; counter++; } else { nrpHolder += pattern[i]; nrps.Add(nrpHolder); nrpHolder = ""; counter = 0; } } for (int i = 0; i < ThreadsInfo.Count; i++) { var context = ThreadsInfo[i].Get_Context(); if(context.Error != null) { context.LogEvent(); offsets.Error = context.Error; } } List registers = new List(); if(ProcessMachineType == MachineType.I386) { for (int i = 0; i < ThreadsInfo.Count; i++) { RegisterInfo regEdi = new RegisterInfo(); regEdi.Register = "EDI"; if (ThreadsInfo[i].Context32.Edi > int.MaxValue) { ThreadsInfo[i].Context32.Edi = ThreadsInfo[i].Context32.Edi - int.MaxValue; } regEdi.RegisterValue = (IntPtr)ThreadsInfo[i].Context32.Edi; regEdi.ThreadID = ThreadsInfo[i].ThreadID; regEdi.StringOffset = -1; regEdi.RegisterOffset = -1; registers.Add(regEdi); RegisterInfo regEsi = new RegisterInfo(); regEsi.Register = "ESI"; if (ThreadsInfo[i].Context32.Esi > int.MaxValue) { ThreadsInfo[i].Context32.Esi = ThreadsInfo[i].Context32.Esi - int.MaxValue; } regEsi.RegisterValue = (IntPtr)ThreadsInfo[i].Context32.Esi; regEsi.ThreadID = ThreadsInfo[i].ThreadID; regEsi.StringOffset = -1; regEsi.RegisterOffset = -1; registers.Add(regEsi); RegisterInfo regEbx = new RegisterInfo(); regEbx.Register = "EBX"; if (ThreadsInfo[i].Context32.Ebx > int.MaxValue) { ThreadsInfo[i].Context32.Ebx = ThreadsInfo[i].Context32.Ebx - int.MaxValue; } regEbx.RegisterValue = (IntPtr)ThreadsInfo[i].Context32.Ebx; regEbx.ThreadID = ThreadsInfo[i].ThreadID; regEbx.StringOffset = -1; regEbx.RegisterOffset = -1; registers.Add(regEbx); RegisterInfo regEdx = new RegisterInfo(); regEdx.Register = "EDX"; if (ThreadsInfo[i].Context32.Edx > int.MaxValue) { ThreadsInfo[i].Context32.Edx = ThreadsInfo[i].Context32.Edx - int.MaxValue; } regEdx.RegisterValue = (IntPtr)ThreadsInfo[i].Context32.Edx; regEdx.ThreadID = ThreadsInfo[i].ThreadID; regEdx.StringOffset = -1; regEdx.RegisterOffset = -1; registers.Add(regEdx); RegisterInfo regEcx = new RegisterInfo(); regEcx.Register = "ECX"; if (ThreadsInfo[i].Context32.Ecx > int.MaxValue) { ThreadsInfo[i].Context32.Ecx = ThreadsInfo[i].Context32.Ecx - int.MaxValue; } regEcx.RegisterValue = (IntPtr)ThreadsInfo[i].Context32.Ecx; regEcx.ThreadID = ThreadsInfo[i].ThreadID; regEcx.StringOffset = -1; regEcx.RegisterOffset = -1; registers.Add(regEcx); RegisterInfo regEax = new RegisterInfo(); regEax.Register = "EAX"; if(ThreadsInfo[i].Context32.Eax > int.MaxValue) { ThreadsInfo[i].Context32.Eax = ThreadsInfo[i].Context32.Eax - int.MaxValue; } regEax.RegisterValue = (IntPtr)ThreadsInfo[i].Context32.Eax; //Arith problem here regEax.ThreadID = ThreadsInfo[i].ThreadID; regEax.StringOffset = -1; regEax.RegisterOffset = -1; registers.Add(regEax); RegisterInfo regEsp = new RegisterInfo(); regEsp.Register = "ESP"; if (ThreadsInfo[i].Context32.Esp > int.MaxValue) { ThreadsInfo[i].Context32.Esp = ThreadsInfo[i].Context32.Esp - int.MaxValue; } regEsp.RegisterValue = (IntPtr)ThreadsInfo[i].Context32.Esp; regEsp.ThreadID = ThreadsInfo[i].ThreadID; regEsp.StringOffset = -1; regEsp.RegisterOffset = -1; registers.Add(regEsp); RegisterInfo regEbp = new RegisterInfo(); regEbp.Register = "EBP"; if (ThreadsInfo[i].Context32.Ebp > int.MaxValue) { ThreadsInfo[i].Context32.Ebp = ThreadsInfo[i].Context32.Ebp - int.MaxValue; } regEbp.RegisterValue = (IntPtr)ThreadsInfo[i].Context32.Ebp; regEbp.ThreadID = ThreadsInfo[i].ThreadID; regEbp.StringOffset = -1; regEbp.RegisterOffset = -1; registers.Add(regEbp); RegisterInfo regEIP = new RegisterInfo(); regEIP.Register = "EIP"; if (ThreadsInfo[i].Context32.Eip > int.MaxValue) { ThreadsInfo[i].Context32.Eip = ThreadsInfo[i].Context32.Eip - int.MaxValue; } regEIP.RegisterValue = (IntPtr)ThreadsInfo[i].Context32.Eip; regEIP.ThreadID = ThreadsInfo[i].ThreadID; registers.Add(regEIP); } for (int i = 0; i < registers.Count; i++) { for (int j = 0; j < ProcessMemoryBasicInfo32.Count; j++) { ulong regionStart = (ulong)ProcessMemoryBasicInfo32[j].BaseAddress; ulong regionEnd = (ulong)ProcessMemoryBasicInfo32[j].BaseAddress + (ulong)ProcessMemoryBasicInfo32[j].RegionSize; if (registers[i].Register != "EIP" && registers[i].Register != "EBP" && (ulong)registers[i].RegisterValue > regionStart && (ulong)registers[i].RegisterValue < regionEnd) { ulong bufferSize = ((ulong)ProcessMemoryBasicInfo32[j].BaseAddress + (ulong)ProcessMemoryBasicInfo32[j].RegionSize) - (ulong)registers[i].RegisterValue; byte[] buffer = new byte[bufferSize]; int bytesRead = 0; ReadProcessMemory(ProcessHandle, registers[i].RegisterValue, buffer, (int)bufferSize, out bytesRead); string memoryString = ""; switch (searchType) { case 0: memoryString = Encoding.Default.GetString(buffer); break; case 1: memoryString = Encoding.Unicode.GetString(buffer); break; case 2: memoryString = Encoding.ASCII.GetString(buffer); break; case 3: memoryString = Encoding.UTF8.GetString(buffer); break; case 4: memoryString = Encoding.UTF7.GetString(buffer); break; case 5: memoryString = Encoding.UTF32.GetString(buffer); break; default: memoryString = Encoding.Default.GetString(buffer); break; } int length = -1; for (int k = 0; k < nrps.Count; k++) { if (memoryString.Contains(nrps[k]) && pattern.Contains(nrps[k])) { if (registers[i].StringOffset == -1) { registers[i].StringOffset = pattern.IndexOf(nrps[k]); } int index = memoryString.IndexOf(nrps[k]); if (registers[i].RegisterOffset == -1) { registers[i].RegisterOffset = index; } length += 3; } } registers[i].BufferSize = length; } else if (registers[i].Register == "EIP") { string EIPValue = ""; switch (searchType) { case 0: EIPValue = Encoding.Default.GetString(BitConverter.GetBytes((uint)registers[i].RegisterValue)); break; case 1: EIPValue = Encoding.Unicode.GetString(BitConverter.GetBytes((uint)registers[i].RegisterValue)); break; case 2: EIPValue = Encoding.ASCII.GetString(BitConverter.GetBytes((uint)registers[i].RegisterValue)); break; case 3: EIPValue = Encoding.UTF8.GetString(BitConverter.GetBytes((uint)registers[i].RegisterValue)); break; case 4: EIPValue = Encoding.UTF7.GetString(BitConverter.GetBytes((uint)registers[i].RegisterValue)); break; case 5: EIPValue = Encoding.UTF32.GetString(BitConverter.GetBytes((uint)registers[i].RegisterValue)); break; default: EIPValue = Encoding.Default.GetString(BitConverter.GetBytes((uint)registers[i].RegisterValue)); break; } EIPValue = EIPValue.TrimEnd(null); if (pattern.Contains(EIPValue)) { registers[i].StringOffset = pattern.IndexOf(EIPValue); } } } if (Utilities.PatternTools.PatternOffset(Utilities.Convert.HexToAscii(registers[i].RegisterValue.ToString("X")), ProcessCore).ReturnValue != "Value not found in pattern.") { if(Utilities.Convert.HexToAscii(registers[i].RegisterValue.ToString("X")).Length > 0) { string regHex = Utilities.Convert.HexToAscii(registers[i].RegisterValue.ToString("X")); string regPos = Utilities.PatternTools.PatternOffset(Utilities.Convert.HexToAscii(registers[i].RegisterValue.ToString("X")), ProcessCore).ReturnValue; if (!String.IsNullOrEmpty(regPos) && regPos.Any(char.IsDigit)) { registers[i].StringOffset = Int32.Parse(Regex.Match(regPos, @"\d+").Value); registers[i].overwritten = true; } } } } for (int i = 0; i < ThreadsInfo.Count; i++) { var pTeb = ThreadsInfo[i].PopulateTEB(); if (pTeb.Error == null) { var sehChain = ThreadsInfo[i].BuildSehChain(); if (sehChain.Error == null) { if (sehChain.ReturnValue.Count > 0) { for (int j = 0; j < sehChain.ReturnValue.Count; j++) { string SEHValue = ""; string nSEHValue = ""; switch (searchType) { case 0: SEHValue = Encoding.Default.GetString(sehChain.ReturnValue[j].Item1); nSEHValue = Encoding.Default.GetString(sehChain.ReturnValue[j].Item2); break; case 1: byte[] sehHolder1 = sehChain.ReturnValue[j].Item1; byte[] sehHolder2 = sehChain.ReturnValue[j].Item2; if (sehChain.ReturnValue[j].Item1[0] == 0x00) { byte[] newSEH = new byte[sehChain.ReturnValue[j].Item1.Length]; Array.Copy(sehChain.ReturnValue[j].Item1, 1, newSEH, 0, sehChain.ReturnValue[j].Item1.Length - 1); newSEH[newSEH.Length - 1] = 0x00; sehHolder1 = newSEH; } if (sehChain.ReturnValue[j].Item2[0] == 0x00) { byte[] newSEH = new byte[sehChain.ReturnValue[j].Item2.Length]; Array.Copy(sehChain.ReturnValue[j].Item2, 1, newSEH, 0, sehChain.ReturnValue[j].Item2.Length - 1); newSEH[newSEH.Length - 1] = 0x00; sehHolder2 = newSEH; } SEHValue = Encoding.Unicode.GetString(sehHolder1); nSEHValue = Encoding.Unicode.GetString(sehHolder2); break; case 2: SEHValue = Encoding.ASCII.GetString(sehChain.ReturnValue[j].Item1); nSEHValue = Encoding.ASCII.GetString(sehChain.ReturnValue[j].Item2); break; case 3: SEHValue = Encoding.UTF8.GetString(sehChain.ReturnValue[j].Item1); nSEHValue = Encoding.UTF8.GetString(sehChain.ReturnValue[j].Item2); break; case 4: SEHValue = Encoding.UTF7.GetString(sehChain.ReturnValue[j].Item1); nSEHValue = Encoding.UTF7.GetString(sehChain.ReturnValue[j].Item2); break; case 5: SEHValue = Encoding.UTF32.GetString(sehChain.ReturnValue[j].Item1); nSEHValue = Encoding.UTF32.GetString(sehChain.ReturnValue[j].Item2); break; default: SEHValue = Encoding.Default.GetString(sehChain.ReturnValue[j].Item1); nSEHValue = Encoding.Default.GetString(sehChain.ReturnValue[j].Item2); break; } char[] sehArray = SEHValue.ToCharArray(); Array.Reverse(sehArray); string ReversedSEHValue = new string(sehArray); RegisterInfo SEH = new RegisterInfo(); char[] nsehArray = nSEHValue.ToCharArray(); Array.Reverse(nsehArray); string nReversedSEHValue = new string(nsehArray); string combinedSeh = SEHValue + nSEHValue; string reversedCombinedSeh = ReversedSEHValue + nReversedSEHValue; if (pattern.Contains(combinedSeh) || pattern.Contains(reversedCombinedSeh)) { SEH.Register = "SEH" + i.ToString(); if (pattern.Contains(reversedCombinedSeh)) { SEH.StringOffset = pattern.IndexOf(reversedCombinedSeh); } else { SEH.StringOffset = pattern.IndexOf(combinedSeh); } SEH.ThreadID = ThreadsInfo[i].ThreadID; SEH.RegisterValue = (IntPtr)BitConverter.ToInt32(sehChain.ReturnValue[j].Item1, 0); registers.Add(SEH); } else if (pattern.Contains(SEHValue) || pattern.Contains(ReversedSEHValue) || pattern.Contains(nSEHValue) || pattern.Contains(nReversedSEHValue)) { SEH.Register = "SEH" + i.ToString(); if (pattern.Contains(ReversedSEHValue)) { SEH.StringOffset = pattern.IndexOf(ReversedSEHValue); } else if(pattern.Contains(SEHValue)) { SEH.StringOffset = pattern.IndexOf(SEHValue); } else if(pattern.Contains(nReversedSEHValue)) { SEH.StringOffset = pattern.IndexOf(nReversedSEHValue); } else { SEH.StringOffset = pattern.IndexOf(nSEHValue); } SEH.ThreadID = ThreadsInfo[i].ThreadID; SEH.RegisterValue = (IntPtr)BitConverter.ToInt32(sehChain.ReturnValue[j].Item1, 0); registers.Add(SEH); } } } } } } } else if(ProcessMachineType == MachineType.x64) { for (int i = 0; i < ThreadsInfo.Count; i++) { RegisterInfo regRax = new RegisterInfo(); regRax.Register = "Rax"; regRax.RegisterValue = (IntPtr)ThreadsInfo[i].Context64.Rax; regRax.ThreadID = ThreadsInfo[i].ThreadID; regRax.StringOffset = -1; regRax.RegisterOffset = -1; registers.Add(regRax); RegisterInfo regRbx = new RegisterInfo(); regRbx.Register = "RBX"; regRbx.RegisterValue = (IntPtr)ThreadsInfo[i].Context64.Rbx; regRbx.ThreadID = ThreadsInfo[i].ThreadID; regRbx.StringOffset = -1; regRbx.RegisterOffset = -1; registers.Add(regRbx); RegisterInfo regRcx = new RegisterInfo(); regRcx.Register = "RCX"; regRcx.RegisterValue = (IntPtr)ThreadsInfo[i].Context64.Rcx; regRcx.ThreadID = ThreadsInfo[i].ThreadID; regRcx.StringOffset = -1; regRcx.RegisterOffset = -1; registers.Add(regRcx); RegisterInfo regRdx = new RegisterInfo(); regRdx.Register = "RDX"; regRdx.RegisterValue = (IntPtr)ThreadsInfo[i].Context64.Rdx; regRdx.ThreadID = ThreadsInfo[i].ThreadID; regRdx.StringOffset = -1; regRdx.RegisterOffset = -1; registers.Add(regRdx); RegisterInfo regRsp = new RegisterInfo(); regRsp.Register = "RSP"; regRsp.RegisterValue = (IntPtr)ThreadsInfo[i].Context64.Rsp; regRsp.ThreadID = ThreadsInfo[i].ThreadID; regRsp.StringOffset = -1; regRsp.RegisterOffset = -1; registers.Add(regRsp); RegisterInfo regRbp = new RegisterInfo(); regRbp.Register = "RBP"; regRbp.RegisterValue = (IntPtr)ThreadsInfo[i].Context64.Rbp; regRbp.ThreadID = ThreadsInfo[i].ThreadID; regRbp.StringOffset = -1; regRbp.RegisterOffset = -1; registers.Add(regRbp); RegisterInfo regRsi = new RegisterInfo(); regRsi.Register = "RSI"; regRsi.RegisterValue = (IntPtr)ThreadsInfo[i].Context64.Rsi; regRsi.ThreadID = ThreadsInfo[i].ThreadID; regRsi.StringOffset = -1; regRsi.RegisterOffset = -1; registers.Add(regRsi); RegisterInfo regRdi = new RegisterInfo(); regRdi.Register = "RDI"; regRdi.RegisterValue = (IntPtr)ThreadsInfo[i].Context64.Rdi; regRdi.ThreadID = ThreadsInfo[i].ThreadID; regRdi.StringOffset = -1; regRdi.RegisterOffset = -1; registers.Add(regRdi); RegisterInfo regR8 = new RegisterInfo(); regR8.Register = "R8"; regR8.RegisterValue = (IntPtr)ThreadsInfo[i].Context64.R8; regR8.ThreadID = ThreadsInfo[i].ThreadID; regR8.StringOffset = -1; regR8.RegisterOffset = -1; registers.Add(regR8); RegisterInfo regR9 = new RegisterInfo(); regR9.Register = "R9"; regR9.RegisterValue = (IntPtr)ThreadsInfo[i].Context64.R9; regR9.ThreadID = ThreadsInfo[i].ThreadID; regR9.StringOffset = -1; regR9.RegisterOffset = -1; registers.Add(regR9); RegisterInfo regR10 = new RegisterInfo(); regR10.Register = "R10"; regR10.RegisterValue = (IntPtr)ThreadsInfo[i].Context64.R10; regR10.ThreadID = ThreadsInfo[i].ThreadID; regR10.StringOffset = -1; regR10.RegisterOffset = -1; registers.Add(regR10); RegisterInfo regR11 = new RegisterInfo(); regR11.Register = "R11"; regR11.RegisterValue = (IntPtr)ThreadsInfo[i].Context64.R11; regR11.ThreadID = ThreadsInfo[i].ThreadID; regR11.StringOffset = -1; regR11.RegisterOffset = -1; registers.Add(regR11); RegisterInfo regR12 = new RegisterInfo(); regR12.Register = "R12"; regR12.RegisterValue = (IntPtr)ThreadsInfo[i].Context64.R12; regR12.ThreadID = ThreadsInfo[i].ThreadID; regR12.StringOffset = -1; regR12.RegisterOffset = -1; registers.Add(regR12); RegisterInfo regR13 = new RegisterInfo(); regR13.Register = "R13"; regR13.RegisterValue = (IntPtr)ThreadsInfo[i].Context64.R13; regR13.ThreadID = ThreadsInfo[i].ThreadID; regR13.StringOffset = -1; regR13.RegisterOffset = -1; registers.Add(regR13); RegisterInfo regR14 = new RegisterInfo(); regR14.Register = "R14"; regR14.RegisterValue = (IntPtr)ThreadsInfo[i].Context64.R14; regR14.ThreadID = ThreadsInfo[i].ThreadID; regR14.StringOffset = -1; regR14.RegisterOffset = -1; registers.Add(regR14); RegisterInfo regR15 = new RegisterInfo(); regR15.Register = "R15"; regR15.RegisterValue = (IntPtr)ThreadsInfo[i].Context64.R15; regR15.ThreadID = ThreadsInfo[i].ThreadID; regR15.StringOffset = -1; regR15.RegisterOffset = -1; registers.Add(regR15); RegisterInfo regRIP = new RegisterInfo(); regRIP.Register = "RIP"; regRIP.RegisterValue = (IntPtr)ThreadsInfo[i].Context64.Rip; regRIP.ThreadID = ThreadsInfo[i].ThreadID; registers.Add(regRIP); } for (int i = 0; i < registers.Count; i++) { for (int j = 0; j < ProcessMemoryBasicInfo64.Count; j++) { ulong regionStart = ProcessMemoryBasicInfo64[j].BaseAddress; ulong regionEnd = ProcessMemoryBasicInfo64[j].BaseAddress + ProcessMemoryBasicInfo64[j].RegionSize; if (registers[i].Register != "RIP" && registers[i].Register != "RBP" && (ulong)registers[i].RegisterValue > regionStart && (ulong)registers[i].RegisterValue < regionEnd) { ulong bufferSize = (ProcessMemoryBasicInfo64[j].BaseAddress + ProcessMemoryBasicInfo64[j].RegionSize) - (ulong)registers[i].RegisterValue; byte[] buffer = new byte[bufferSize]; int bytesRead = 0; ReadProcessMemory(ProcessHandle, registers[i].RegisterValue, buffer, (int)bufferSize, out bytesRead); string memoryString = ""; switch (searchType) { case 0: memoryString = Encoding.Default.GetString(buffer); break; case 1: memoryString = Encoding.Unicode.GetString(buffer); break; case 2: memoryString = Encoding.ASCII.GetString(buffer); break; case 3: memoryString = Encoding.UTF8.GetString(buffer); break; case 4: memoryString = Encoding.UTF7.GetString(buffer); break; case 5: memoryString = Encoding.UTF32.GetString(buffer); break; default: memoryString = Encoding.Default.GetString(buffer); break; } int length = 0; for (int k = 0; k < nrps.Count; k++) { if (memoryString.Contains(nrps[k]) && pattern.Contains(nrps[k])) { if (registers[i].StringOffset == -1) { registers[i].StringOffset = pattern.IndexOf(nrps[k]); } int index = memoryString.IndexOf(nrps[k]); if (registers[i].RegisterOffset == -1) { registers[i].RegisterOffset = index; } length += 3; } } registers[i].BufferSize = length; } else if(registers[i].Register != "RIP") { string RIPValue = ""; switch (searchType) { case 0: RIPValue = Encoding.Default.GetString(BitConverter.GetBytes((ulong)registers[i].RegisterValue)); break; case 1: RIPValue = Encoding.Unicode.GetString(BitConverter.GetBytes((ulong)registers[i].RegisterValue)); break; case 2: RIPValue = Encoding.ASCII.GetString(BitConverter.GetBytes((ulong)registers[i].RegisterValue)); break; case 3: RIPValue = Encoding.UTF8.GetString(BitConverter.GetBytes((ulong)registers[i].RegisterValue)); break; case 4: RIPValue = Encoding.UTF7.GetString(BitConverter.GetBytes((ulong)registers[i].RegisterValue)); break; case 5: RIPValue = Encoding.UTF32.GetString(BitConverter.GetBytes((ulong)registers[i].RegisterValue)); break; default: RIPValue = Encoding.Default.GetString(BitConverter.GetBytes((ulong)registers[i].RegisterValue)); break; } char[] ripArray = RIPValue.ToCharArray(); Array.Reverse(ripArray); RIPValue = new string(ripArray); if (pattern.Contains(RIPValue)) { registers[i].StringOffset = pattern.IndexOf(RIPValue); } } } if (Utilities.PatternTools.PatternOffset(Utilities.Convert.HexToAscii(registers[i].RegisterValue.ToString("X")), ProcessCore).ReturnValue != "Value not found in pattern.") { if (Utilities.Convert.HexToAscii(registers[i].RegisterValue.ToString("X")).Length > 0) { string regHex = Utilities.Convert.HexToAscii(registers[i].RegisterValue.ToString("X")); string regPos = Utilities.PatternTools.PatternOffset(Utilities.Convert.HexToAscii(registers[i].RegisterValue.ToString("X")), ProcessCore).ReturnValue; if (!String.IsNullOrEmpty(regPos) && regPos.Any(char.IsDigit)) { registers[i].StringOffset = Int32.Parse(Regex.Match(regPos, @"\d+").Value); registers[i].overwritten = true; } } } } for(int i = 0; i < ThreadsInfo.Count; i++) { var pTeb = ThreadsInfo[i].PopulateTEB(); if(pTeb.Error == null) { var sehChain = ThreadsInfo[i].BuildSehChain(); if(sehChain.Error == null) { if(sehChain.ReturnValue.Count > 0) { for(int j = 0; j < sehChain.ReturnValue.Count; j++) { string SEHValue = ""; string nSEHValue = ""; switch (searchType) { case 0: SEHValue = Encoding.Default.GetString(sehChain.ReturnValue[j].Item1); nSEHValue = Encoding.Default.GetString(sehChain.ReturnValue[j].Item2); break; case 1: byte[] sehHolder1 = sehChain.ReturnValue[j].Item1; byte[] sehHolder2 = sehChain.ReturnValue[j].Item2; if (sehChain.ReturnValue[j].Item1[0] == 0x00) { byte[] newSEH = new byte[sehChain.ReturnValue[j].Item1.Length]; Array.Copy(sehChain.ReturnValue[j].Item1, 1, newSEH, 0, sehChain.ReturnValue[j].Item1.Length - 1); newSEH[newSEH.Length - 1] = 0x00; sehHolder1 = newSEH; } if (sehChain.ReturnValue[j].Item2[0] == 0x00) { byte[] newSEH = new byte[sehChain.ReturnValue[j].Item2.Length]; Array.Copy(sehChain.ReturnValue[j].Item2, 1, newSEH, 0, sehChain.ReturnValue[j].Item2.Length - 1); newSEH[newSEH.Length - 1] = 0x00; sehHolder2 = newSEH; } SEHValue = Encoding.Unicode.GetString(sehHolder1); nSEHValue = Encoding.Unicode.GetString(sehHolder2); break; case 2: SEHValue = Encoding.ASCII.GetString(sehChain.ReturnValue[j].Item1); nSEHValue = Encoding.ASCII.GetString(sehChain.ReturnValue[j].Item2); break; case 3: SEHValue = Encoding.UTF8.GetString(sehChain.ReturnValue[j].Item1); nSEHValue = Encoding.UTF8.GetString(sehChain.ReturnValue[j].Item2); break; case 4: SEHValue = Encoding.UTF7.GetString(sehChain.ReturnValue[j].Item1); nSEHValue = Encoding.UTF7.GetString(sehChain.ReturnValue[j].Item2); break; case 5: SEHValue = Encoding.UTF32.GetString(sehChain.ReturnValue[j].Item1); nSEHValue = Encoding.UTF32.GetString(sehChain.ReturnValue[j].Item2); break; default: SEHValue = Encoding.Default.GetString(sehChain.ReturnValue[j].Item1); nSEHValue = Encoding.Default.GetString(sehChain.ReturnValue[j].Item2); break; } char[] sehArray = SEHValue.ToCharArray(); Array.Reverse(sehArray); string ReversedSEHValue = new string(sehArray); RegisterInfo SEH = new RegisterInfo(); char[] nsehArray = nSEHValue.ToCharArray(); Array.Reverse(nsehArray); string nReversedSEHValue = new string(nsehArray); string combinedSeh = SEHValue + nSEHValue; string reversedCombinedSeh = ReversedSEHValue + nReversedSEHValue; if (pattern.Contains(combinedSeh) || pattern.Contains(reversedCombinedSeh)) { SEH.Register = "SEH" + i.ToString(); if (pattern.Contains(reversedCombinedSeh)) { SEH.StringOffset = pattern.IndexOf(reversedCombinedSeh); } else { SEH.StringOffset = pattern.IndexOf(combinedSeh); } SEH.ThreadID = ThreadsInfo[i].ThreadID; SEH.RegisterValue = (IntPtr)BitConverter.ToInt64(sehChain.ReturnValue[j].Item1, 0); registers.Add(SEH); } else if (pattern.Contains(SEHValue) || pattern.Contains(ReversedSEHValue) || pattern.Contains(nSEHValue) || pattern.Contains(nReversedSEHValue)) { SEH.Register = "SEH" + i.ToString(); if (pattern.Contains(ReversedSEHValue)) { SEH.StringOffset = pattern.IndexOf(ReversedSEHValue); } else if (pattern.Contains(SEHValue)) { SEH.StringOffset = pattern.IndexOf(SEHValue); } else if (pattern.Contains(nReversedSEHValue)) { SEH.StringOffset = pattern.IndexOf(nReversedSEHValue); } else { SEH.StringOffset = pattern.IndexOf(nSEHValue); } SEH.ThreadID = ThreadsInfo[i].ThreadID; SEH.RegisterValue = (IntPtr)BitConverter.ToInt64(sehChain.ReturnValue[j].Item1, 0); registers.Add(SEH); } } } } } } } else { offsets.Error = new ERCException("Critical Error: Process returned incompatible machine type."); offsets.LogEvent(); } offsets.ReturnValue = registers; return offsets; } #endregion #endregion #region BoyerMoore Search ByteArrays /// /// Private function, BoyerMoore string search algorithm modified to search for sets of bytes in a byte array. /// Takes two byte arrays, array to be searched and array to search for. /// private static int ByteIndexOf(byte[] haystack, byte[] needle) { if (needle.Length == 0) { return 0; } int[] charTable = MakeCharTable(needle); int[] offsetTable = MakeOffsetTable(needle); for (int i = needle.Length - 1; i < haystack.Length;) { int j; for (j = needle.Length - 1; needle[j] == haystack[i]; --i, --j) { if (j == 0) { return i; } } i += Math.Max(offsetTable[needle.Length - 1 - j], charTable[haystack[i]]); } return -1; } private static int[] MakeCharTable(byte[] needle) { const int ALPHABET_SIZE = 256; int[] table = new int[ALPHABET_SIZE]; for (int i = 0; i < table.Length; ++i) { table[i] = needle.Length; } for (int i = 0; i < needle.Length - 1; ++i) { table[needle[i]] = needle.Length - 1 - i; } return table; } private static int[] MakeOffsetTable(byte[] needle) { int[] table = new int[needle.Length]; int lastPrefixPosition = needle.Length; for (int i = needle.Length - 1; i >= 0; --i) { if (IsPrefix(needle, i + 1)) { lastPrefixPosition = i + 1; } table[needle.Length - 1 - i] = lastPrefixPosition - i + needle.Length - 1; } for (int i = 0; i < needle.Length - 1; ++i) { int slen = SuffixLength(needle, i); table[slen] = needle.Length - 1 - i + slen; } return table; } private static bool IsPrefix(byte[] needle, int p) { for (int i = p, j = 0; i < needle.Length; ++i, ++j) { if (needle[i] != needle[j]) { return false; } } return true; } private static int SuffixLength(byte[] needle, int p) { int len = 0; for (int i = p, j = needle.Length - 1; i >= 0 && needle[i] == needle[j]; --i, --j) { len += 1; } return len; } #endregion #region CreateExcludesList /// /// Creates a list of modules to exclude from a search of memory. /// /// Returns an ErcResult containing a list of stringss public List CreateExcludesList(bool aslr = false, bool safeseh = false, bool rebase = false, bool nxcompat = false, bool osdll = false) { List excludedModules = new List(); for(int i = 0; i < ModulesInfo.Count; i++) { bool add = false; if(aslr == true && ModulesInfo[i].ModuleASLR == true) { add = true; } if (safeseh == true && ModulesInfo[i].ModuleSafeSEH == true) { add = true; } if (rebase == true && ModulesInfo[i].ModuleRebase == true) { add = true; } if (nxcompat == true && ModulesInfo[i].ModuleNXCompat == true) { add = true; } if (osdll == true && ModulesInfo[i].ModuleOsDll == true) { add = true; } if(add == true) { excludedModules.Add(ModulesInfo[i].ModulePath); } } return excludedModules; } #endregion #region Accessors #region ToString /// /// Override of the ToString method. Returns information about the process in a pleasantly formatted string /// /// A string public override string ToString() { string ret = ""; ret += "Process Name = " + ProcessName + Environment.NewLine; ret += "Process Description = " + ProcessDescription + Environment.NewLine; ret += "Process Path = " + ProcessPath + Environment.NewLine; ret += "Process ID = " + ProcessID + Environment.NewLine; if(ProcessMachineType == MachineType.I386) { ret += "Process Handle = 0x" + ProcessHandle.ToString("X8") + Environment.NewLine; } else { ret += "Process Handle = 0x" + ProcessHandle.ToString("X16") + Environment.NewLine; } ret += "Process Machine Type = " + ProcessMachineType.ToString() + Environment.NewLine; return ret; } #endregion #region Get Modules Handles /// /// Returns a list of module handles associated with the process. /// /// Returns a dictionary containing the handle and path of each module public ErcResult> GetModuleHandles() { ErcResult> ret = new ErcResult>(ProcessCore); if (ProcessModuleHandles.Count > 0) { ret.ReturnValue = ProcessModuleHandles; return ret; } else { ret.Error = new ERCException("Error: An unknown eroor has occured whilst populating the modules list for this process. Check the error log for more detailed information."); return ret; } } #endregion #region Get Module Information /// /// Gets the list of ModuleInfo objects associated with the current process. /// /// Returns an ErcResult containing a list of ModuleInfo objects public ErcResult> GetProcessModuleInformation() { ErcResult> ret = new ErcResult>(ProcessCore); if(ModulesInfo.Count > 0) { ret.ReturnValue = ModulesInfo; return ret; } else { ret.Error = new ERCException("Error: An unknown eroor has occured whilst populating the modules list for this process. Check the error log for more detailed information."); return ret; } } #endregion #region Get Thread Information /// /// Gets the list of ThreadInfo objects associated with the current process. /// /// Returns an ErcResult containing a list of ThreadInfo objects public ErcResult> GetProcessThreadInformation() { ErcResult> ret = new ErcResult>(ProcessCore); if (ThreadsInfo.Count > 0) { ret.ReturnValue = ThreadsInfo; return ret; } else { ret.Error = new ERCException("Error: An unknown eroor has occured whilst populating the threads list for this process. Check the error log for more detailed information."); return ret; } } #endregion #region Dump Memory Region /// /// Reads process memory from a specific address for a set number of bytes. /// /// The address to start reading from. /// Number of bytes to read. /// Returns a bytes array containing the specified contents of process memory. public ErcResult DumpMemoryRegion(IntPtr startAddress, int length) { ErcResult result = new ErcResult(ProcessCore); byte[] bytes = new byte[length]; try { int retValue = ErcCore.ReadProcessMemory(ProcessHandle, startAddress, bytes, length, out int bytesRead); if (retValue == 0) { ERCException ex = new ERCException(new Win32Exception(Marshal.GetLastWin32Error()).Message); result.ReturnValue = bytes; throw ex; } else { result.ReturnValue = bytes; } } catch(Exception e) { result.Error = e; } return result; } #endregion #endregion } } ================================================ FILE: ERC/ERC/PtrRemover.cs ================================================ using System; using System.Collections.Generic; using System.Linq; namespace ERC.Utilities { /// /// Contains methods for identifying and removing pointers to unwanted data. /// public static class PtrRemover { /// /// Removes pointers which contain unwanted bytes. /// /// MachineType architecture of the associated process. /// The list from which to remove the pointers /// If a pointer contains any of these bytes it will be discarded /// Returns a ErcResult of List IntPtr public static List RemovePointers(MachineType mt, List srcList, byte[] bytes) { if (bytes == null || bytes.Length == 0) { return srcList; } List outText = new List(); bool nullByte = false; foreach (byte b in bytes) { if (b == 0x00) { nullByte = true; } } for (int i = 0; i < srcList.Count; i++) { bool removed = false; var ptr = BitConverter.GetBytes((int)srcList[i]); for(int j = 0; j < ptr.Length; j++) { for(int k = 0; k < bytes.Length; k++) { if (bytes[k] == ptr[j] && removed == false) { srcList.RemoveAt(i); removed = true; i--; continue; } if(mt == MachineType.I386 && removed == false && nullByte == true) { if(srcList[i].ToString("X8").Length < 7) { srcList.RemoveAt(i); removed = true; i--; continue; } } else if(mt == MachineType.x64 && removed == false && nullByte == true) { if (srcList[i].ToString("X").Length < 15) { srcList.RemoveAt(i); removed = true; i--; continue; } } } } } return srcList; } /// /// Removes pointers which contain unwanted bytes. /// /// MachineType architecture of the associated process. /// The list from which to remove the pointers /// If a pointer contains any of these bytes it will be discarded /// Returns a ErcResult of Dictionary IntPtr, String public static Dictionary RemovePointers(MachineType mt, Dictionary srcList, byte[] bytes) { if(bytes == null || bytes.Length == 0) { return srcList; } bool nullByte = false; foreach(byte b in bytes) { if(b == 0x00) { nullByte = true; } } for (int i = 0; i < srcList.Count; i++) { bool removed = false; var ptr = BitConverter.GetBytes((long)srcList.ElementAt(i).Key); for (int j = 0; j < ptr.Length; j++) { for (int k = 0; k < bytes.Length; k++) { if (bytes[k] == ptr[j] && removed == false) { srcList.Remove(srcList.ElementAt(i).Key); removed = true; i--; continue; } if (mt == MachineType.I386 && removed == false && nullByte == true) { if (srcList.ElementAt(i).Key.ToString("X").Length < 7) { srcList.Remove(srcList.ElementAt(i).Key); removed = true; i--; continue; } } else if (mt == MachineType.x64 && removed == false && nullByte == true) { if (srcList.ElementAt(i).Key.ToString("X").Length < 15) { srcList.Remove(srcList.ElementAt(i).Key); removed = true; i--; continue; } } } } } return srcList; } #region Remove Pointers Protection /// /// Removes pointers from a dictionary when pointers do not have the protection level specified. /// /// ProcessInfo object of the associated process. /// List of pointers. /// Specified protection level of pointers. /// Returns a Dictionary of Intptr, string public static List RemovePointersProtection(ProcessInfo info, List srcList, string protection = "exec") { if (protection == null) { return srcList; } string[] elements = protection.Split(','); if(elements.Length > 3) { throw new ERCException("Supplied protection string is not supported."); } bool read = false, write = false, exec = false, all = false; foreach(string s in elements) { if (s.Contains("read")) { read = true; } else if (s.Contains("write")) { write = true; } else if (s.Contains("exec")) { exec = true; } else if (s.Contains("all")) { all = true; } } protection = ""; if(read == true) { protection += "read"; } if(write == true) { if(protection.Length > 0) { protection += ","; } protection += "write"; } if (exec == true) { if (protection.Length > 0) { protection += ","; } protection += "exec"; } if(all == true) { protection = "all"; } uint[] acceptedProtectionValues = new uint[0]; switch (protection.ToLower()) { case "all": return srcList; case "read": acceptedProtectionValues = new uint[4]; acceptedProtectionValues[0] = 0x02; acceptedProtectionValues[1] = 0x04; acceptedProtectionValues[2] = 0x20; acceptedProtectionValues[3] = 0x40; break; case "write": acceptedProtectionValues = new uint[4]; acceptedProtectionValues[0] = 0x04; acceptedProtectionValues[1] = 0x08; acceptedProtectionValues[2] = 0x40; acceptedProtectionValues[3] = 0x80; break; case "exec": acceptedProtectionValues = new uint[4]; acceptedProtectionValues[0] = 0x10; acceptedProtectionValues[1] = 0x20; acceptedProtectionValues[2] = 0x40; acceptedProtectionValues[3] = 0x80; break; case "read,write": acceptedProtectionValues = new uint[6]; acceptedProtectionValues[0] = 0x02; acceptedProtectionValues[1] = 0x04; acceptedProtectionValues[2] = 0x08; acceptedProtectionValues[3] = 0x20; acceptedProtectionValues[4] = 0x40; acceptedProtectionValues[5] = 0x80; break; case "read,exec": acceptedProtectionValues = new uint[6]; acceptedProtectionValues[0] = 0x02; acceptedProtectionValues[1] = 0x04; acceptedProtectionValues[2] = 0x10; acceptedProtectionValues[3] = 0x20; acceptedProtectionValues[4] = 0x40; acceptedProtectionValues[5] = 0x80; break; case "write,exec": acceptedProtectionValues = new uint[6]; acceptedProtectionValues[0] = 0x04; acceptedProtectionValues[1] = 0x08; acceptedProtectionValues[2] = 0x10; acceptedProtectionValues[3] = 0x20; acceptedProtectionValues[4] = 0x40; acceptedProtectionValues[5] = 0x80; break; case "read,write,exec": acceptedProtectionValues = new uint[7]; acceptedProtectionValues[0] = 0x02; acceptedProtectionValues[1] = 0x04; acceptedProtectionValues[2] = 0x08; acceptedProtectionValues[3] = 0x10; acceptedProtectionValues[4] = 0x20; acceptedProtectionValues[5] = 0x40; acceptedProtectionValues[6] = 0x80; break; default: throw new ERCException("Supplied protection string is not supported."); } for(int i = 0; i < srcList.Count; i++) { IntPtr ptr = srcList[i]; if (info.ProcessMachineType == MachineType.I386) { for (int j = 0; j < info.ProcessMemoryBasicInfo32.Count; j++) { ulong topAddress = (ulong)info.ProcessMemoryBasicInfo32[j].BaseAddress + (ulong)info.ProcessMemoryBasicInfo32[j].RegionSize; if ((ulong)srcList[i] > (ulong)info.ProcessMemoryBasicInfo32[j].BaseAddress && (ulong)srcList[i] < topAddress) { if (!acceptedProtectionValues.Contains(info.ProcessMemoryBasicInfo32[j].AllocationProtect) && srcList.Contains(ptr)) { srcList.Remove(ptr); } } } } else { for (int j = 0; j < info.ProcessMemoryBasicInfo64.Count; j++) { ulong topAddress = (ulong)info.ProcessMemoryBasicInfo64[j].BaseAddress + (ulong)info.ProcessMemoryBasicInfo64[j].RegionSize; if ((ulong)srcList[i] > (ulong)info.ProcessMemoryBasicInfo64[j].BaseAddress && (ulong)srcList[i] < topAddress) { if (!acceptedProtectionValues.Contains(info.ProcessMemoryBasicInfo64[j].AllocationProtect) && srcList.Contains(ptr)) { srcList.Remove(ptr); } } } } } return srcList; } /// /// Removes pointers from a dictionary when pointers do not have the protection level specified. /// /// ProcessInfo object of the associated process. /// List of pointers. /// Specified protection level of pointers. /// Returns a Dictionary of Intptr, string public static List RemovePointersProtection(ProcessInfo info, List srcList, uint protection) { for (int i = 0; i < srcList.Count; i++) { IntPtr ptr = srcList[i]; if (info.ProcessMachineType == MachineType.I386) { for (int j = 0; j < info.ProcessMemoryBasicInfo32.Count; j++) { ulong topAddress = (ulong)info.ProcessMemoryBasicInfo32[j].BaseAddress + (ulong)info.ProcessMemoryBasicInfo32[j].RegionSize; if ((ulong)srcList[i] > (ulong)info.ProcessMemoryBasicInfo32[j].BaseAddress && (ulong)srcList[i] < topAddress) { if (protection != info.ProcessMemoryBasicInfo32[j].AllocationProtect && srcList.Contains(ptr)) { srcList.Remove(ptr); i--; } } } } else { for (int j = 0; j < info.ProcessMemoryBasicInfo64.Count; j++) { ulong topAddress = (ulong)info.ProcessMemoryBasicInfo64[j].BaseAddress + (ulong)info.ProcessMemoryBasicInfo64[j].RegionSize; if ((ulong)srcList[i] > (ulong)info.ProcessMemoryBasicInfo64[j].BaseAddress && (ulong)srcList[i] < topAddress) { if (protection != info.ProcessMemoryBasicInfo64[j].AllocationProtect && srcList.Contains(ptr)) { srcList.Remove(ptr); i--; } } } } } return srcList; } } #endregion } ================================================ FILE: ERC/ERC/RopChainGenerator32.cs ================================================ using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.IO; using System.Linq; using System.Runtime.InteropServices; using System.Threading.Tasks; using System.Windows; using ERC; namespace ERC.Utilities { /// Attempts to create Rop chains from 32 bit processes. public class RopChainGenerator32 { #region Class Variables private const int MEM_COMMIT = 0x1000; /// /// Contains a ROP chain which calls the VirtualAlloc method. /// public List> VirtualAllocChain = new List >(); /// /// Contains a ROP chain which calls the VirtualAlloc method. /// public List> HeapCreateChain = new List>(); /// /// Contains a ROP chain which calls the VirtualAlloc method. /// public List> VirtualProtectChain = new List>(); /// /// Contains a ROP chain which calls the VirtualAlloc method. /// public List> WriteProcessMemoryChain = new List>(); RopMethod Methods; Dictionary ApiAddresses = new Dictionary(); List RopNops = new List(); List opcodes32 = new List(); internal X86Lists x86Opcodes; internal X86Lists usableX86Opcodes; internal ProcessInfo RcgInfo; #endregion #region Constructor /// /// Constructor. /// /// The ProcessInfo object.Integer identifying which Rop mehtods to use public RopChainGenerator32(ProcessInfo _info) { if (_info.ProcessMachineType == MachineType.I386) { x86Opcodes = new X86Lists(); } else { throw new ArgumentException("Fatal Error: Unsupported processor version."); } RcgInfo = _info; //Populate 32 bit list byte[] pushEax = new byte[] { 0x50 }; byte[] pushEbx = new byte[] { 0x53 }; byte[] pushEcx = new byte[] { 0x51 }; byte[] pushEdx = new byte[] { 0x52 }; byte[] pushEsp = new byte[] { 0x54 }; byte[] pushEbp = new byte[] { 0x55 }; byte[] pushEsi = new byte[] { 0x56 }; byte[] pushEdi = new byte[] { 0x57 }; byte[] popEax = new byte[] { 0x58 }; byte[] popEbx = new byte[] { 0x5B }; byte[] popEcx = new byte[] { 0x59 }; byte[] popEdx = new byte[] { 0x5A }; byte[] popEsp = new byte[] { 0x5C }; byte[] popEbp = new byte[] { 0x5D }; byte[] popEsi = new byte[] { 0x5E }; byte[] popEdi = new byte[] { 0x5F }; byte[] pushad = new byte[] { 0x60 }; byte[] incEax = new byte[] { 0X40 }; byte[] incEbx = new byte[] { 0X43 }; byte[] incEcx = new byte[] { 0X41 }; byte[] incEdx = new byte[] { 0X42 }; byte[] incEbp = new byte[] { 0X45 }; byte[] incEsp = new byte[] { 0X44 }; byte[] incEsi = new byte[] { 0X46 }; byte[] incEdi = new byte[] { 0X47 }; byte[] decEax = new byte[] { 0X48 }; byte[] decEbx = new byte[] { 0X4B }; byte[] decEcx = new byte[] { 0X49 }; byte[] decEdx = new byte[] { 0X4A }; byte[] decEbp = new byte[] { 0X4D }; byte[] decEsp = new byte[] { 0X4C }; byte[] decEsi = new byte[] { 0X4E }; byte[] decEdi = new byte[] { 0X4F }; byte[] jmpEsp = new byte[] { 0xFF, 0xE4 }; byte[] callEsp = new byte[] { 0xFF, 0xD4 }; byte[] xorEax = new byte[] { 0x31, 0xC0 }; byte[] xorEbx = new byte[] { 0x31, 0xD8 }; byte[] xorEcx = new byte[] { 0x31, 0xC9 }; byte[] xorEdx = new byte[] { 0x31, 0xD2 }; byte[] xorEsi = new byte[] { 0x31, 0xF6 }; byte[] xorEdi = new byte[] { 0x31, 0xFF }; byte[] add = new byte[] { 0x03 }; byte[] sub = new byte[] { 0x2B }; byte[] mov = new byte[] { 0x8B }; byte[] and = new byte[] { 0x83 }; opcodes32.Add(pushEax); opcodes32.Add(pushEbx); opcodes32.Add(pushEcx); opcodes32.Add(pushEdx); opcodes32.Add(pushEsp); opcodes32.Add(pushEbp); opcodes32.Add(pushEsi); opcodes32.Add(pushEdi); opcodes32.Add(popEax); opcodes32.Add(popEbx); opcodes32.Add(popEcx); opcodes32.Add(popEdx); opcodes32.Add(popEsp); opcodes32.Add(popEbp); opcodes32.Add(popEsi); opcodes32.Add(popEdi); opcodes32.Add(pushad); opcodes32.Add(incEax); opcodes32.Add(incEbx); opcodes32.Add(incEcx); opcodes32.Add(incEdx); opcodes32.Add(incEbp); opcodes32.Add(incEsp); opcodes32.Add(incEsi); opcodes32.Add(incEdi); opcodes32.Add(decEax); opcodes32.Add(decEbx); opcodes32.Add(decEcx); opcodes32.Add(decEdx); opcodes32.Add(decEbp); opcodes32.Add(decEsp); opcodes32.Add(decEsi); opcodes32.Add(decEdi); opcodes32.Add(jmpEsp); opcodes32.Add(callEsp); opcodes32.Add(xorEax); opcodes32.Add(xorEbx); opcodes32.Add(xorEcx); opcodes32.Add(xorEdx); opcodes32.Add(xorEsi); opcodes32.Add(xorEdi); opcodes32.Add(add); opcodes32.Add(sub); opcodes32.Add(mov); opcodes32.Add(and); } #endregion #region GenerateRopGadgets32 /// /// Creates a list of ROP gadgets for a specific process. /// /// Takes a byte array of values used to disqualify ROP gadgets /// A list of modules to be excluded from the search for ROP gadgets /// Returns an ErcResult string containing public ErcResult GenerateRopGadgets32(byte[] ptrsToExclude = null, List excludes = null) { ErcResult RopChain = new ErcResult(RcgInfo.ProcessCore); x86Opcodes = new X86Lists(); var ret1 = GetApiAddresses(RcgInfo); if (ret1.Error != null && ApiAddresses.Count <= 0) { ErcResult failed = new ErcResult(RcgInfo.ProcessCore); failed.ReturnValue = "An error has occured, check log file for more details."; failed.Error = ret1.Error; return failed; } var ret2 = GetRopNops(excludes); if (ret1.Error != null && RopNops.Count <= 0) { ErcResult failed = new ErcResult(RcgInfo.ProcessCore); failed.ReturnValue = "An error has occured, check log file for more details."; failed.Error = ret1.Error; return failed; } var ret3 = PopulateOpcodes(RcgInfo); optimiseLists(RcgInfo); if(ptrsToExclude != null) { usableX86Opcodes.pushEax = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.pushEax, ptrsToExclude); usableX86Opcodes.pushEbx = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.pushEbx, ptrsToExclude); usableX86Opcodes.pushEcx = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.pushEcx, ptrsToExclude); usableX86Opcodes.pushEdx = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.pushEdx, ptrsToExclude); usableX86Opcodes.pushEsp = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.pushEsp, ptrsToExclude); usableX86Opcodes.pushEbp = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.pushEbp, ptrsToExclude); usableX86Opcodes.pushEsi = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.pushEsi, ptrsToExclude); usableX86Opcodes.pushEdi = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.pushEdi, ptrsToExclude); usableX86Opcodes.jmpEsp = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.jmpEsp, ptrsToExclude); usableX86Opcodes.callEsp = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.callEsp, ptrsToExclude); usableX86Opcodes.xorEax = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.xorEax, ptrsToExclude); usableX86Opcodes.xorEbx = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.xorEbx, ptrsToExclude); usableX86Opcodes.xorEcx = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.xorEcx, ptrsToExclude); usableX86Opcodes.xorEdx = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.xorEdx, ptrsToExclude); usableX86Opcodes.xorEsi = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.xorEsi, ptrsToExclude); usableX86Opcodes.xorEdi = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.xorEdi, ptrsToExclude); usableX86Opcodes.popEax = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.popEax, ptrsToExclude); usableX86Opcodes.popEbx = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.popEbx, ptrsToExclude); usableX86Opcodes.popEcx = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.popEcx, ptrsToExclude); usableX86Opcodes.popEdx = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.popEdx, ptrsToExclude); usableX86Opcodes.popEsp = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.popEsp, ptrsToExclude); usableX86Opcodes.popEbp = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.popEbp, ptrsToExclude); usableX86Opcodes.popEsi = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.popEsi, ptrsToExclude); usableX86Opcodes.popEdi = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.popEdi, ptrsToExclude); usableX86Opcodes.pushad = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.pushad, ptrsToExclude); usableX86Opcodes.incEax = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.incEax, ptrsToExclude); usableX86Opcodes.incEbx = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.incEbx, ptrsToExclude); usableX86Opcodes.incEcx = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.incEcx, ptrsToExclude); usableX86Opcodes.incEdx = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.incEdx, ptrsToExclude); usableX86Opcodes.incEbp = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.incEbp, ptrsToExclude); usableX86Opcodes.incEsp = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.incEsp, ptrsToExclude); usableX86Opcodes.incEsi = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.incEsi, ptrsToExclude); usableX86Opcodes.incEdi = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.incEdi, ptrsToExclude); usableX86Opcodes.decEax = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.decEax, ptrsToExclude); usableX86Opcodes.decEbx = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.decEbx, ptrsToExclude); usableX86Opcodes.decEcx = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.decEcx, ptrsToExclude); usableX86Opcodes.decEdx = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.decEdx, ptrsToExclude); usableX86Opcodes.decEbp = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.decEbp, ptrsToExclude); usableX86Opcodes.decEsp = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.decEsp, ptrsToExclude); usableX86Opcodes.decEsi = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.decEsi, ptrsToExclude); usableX86Opcodes.decEdi = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.decEdi, ptrsToExclude); usableX86Opcodes.add = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.add, ptrsToExclude); usableX86Opcodes.sub = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.sub, ptrsToExclude); usableX86Opcodes.mov = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.mov, ptrsToExclude); usableX86Opcodes.and = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.and, ptrsToExclude); } DisplayOutput.RopChainGadgets32(this, true); return RopChain; } #endregion #region GenerateRopChain32 /// /// Creates a RopChain for a specific process. /// /// Takes a byte array of values used to disqualify ROP gadgets /// A Address to be used as the start location for which memory will be made executable /// A list of modules to be excluded from the search for ROP gadgets /// Returns an ErcResult string containing public ErcResult GenerateRopChain32(byte[] ptrsToExclude, byte[] startAddress = null, List excludes = null, RopMethod methods = RopMethod.All) { Methods = methods; ErcResult RopChain = new ErcResult(RcgInfo.ProcessCore); x86Opcodes = new X86Lists(); var ret1 = GetApiAddresses(RcgInfo); if (ret1.Error != null && ApiAddresses.Count <= 0) { ErcResult failed = new ErcResult(RcgInfo.ProcessCore); failed.ReturnValue = "An error has occured, check log file for more details."; failed.Error = ret1.Error; return failed; } if(excludes != null) { var ret2 = GetRopNops(excludes); if (ret1.Error != null && RopNops.Count <= 0) { ErcResult failed = new ErcResult(RcgInfo.ProcessCore); failed.ReturnValue = "An error has occured, check log file for more details."; failed.Error = ret1.Error; return failed; } } else { var ret2 = GetRopNops(); if (ret1.Error != null && RopNops.Count <= 0) { ErcResult failed = new ErcResult(RcgInfo.ProcessCore); failed.ReturnValue = "An error has occured, check log file for more details."; failed.Error = ret1.Error; return failed; } } var ret3 = PopulateOpcodes(RcgInfo); optimiseLists(RcgInfo); usableX86Opcodes.pushEax = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.pushEax, ptrsToExclude); usableX86Opcodes.pushEbx = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.pushEbx, ptrsToExclude); usableX86Opcodes.pushEcx = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.pushEcx, ptrsToExclude); usableX86Opcodes.pushEdx = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.pushEdx, ptrsToExclude); usableX86Opcodes.pushEsp = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.pushEsp, ptrsToExclude); usableX86Opcodes.pushEbp = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.pushEbp, ptrsToExclude); usableX86Opcodes.pushEsi = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.pushEsi, ptrsToExclude); usableX86Opcodes.pushEdi = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.pushEdi, ptrsToExclude); usableX86Opcodes.jmpEsp = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.jmpEsp, ptrsToExclude); usableX86Opcodes.callEsp = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.callEsp, ptrsToExclude); usableX86Opcodes.xorEax = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.xorEax, ptrsToExclude); usableX86Opcodes.xorEbx = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.xorEbx, ptrsToExclude); usableX86Opcodes.xorEcx = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.xorEcx, ptrsToExclude); usableX86Opcodes.xorEdx = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.xorEdx, ptrsToExclude); usableX86Opcodes.xorEsi = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.xorEsi, ptrsToExclude); usableX86Opcodes.xorEdi = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.xorEdi, ptrsToExclude); usableX86Opcodes.popEax = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.popEax, ptrsToExclude); usableX86Opcodes.popEbx = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.popEbx, ptrsToExclude); usableX86Opcodes.popEcx = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.popEcx, ptrsToExclude); usableX86Opcodes.popEdx = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.popEdx, ptrsToExclude); usableX86Opcodes.popEsp = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.popEsp, ptrsToExclude); usableX86Opcodes.popEbp = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.popEbp, ptrsToExclude); usableX86Opcodes.popEsi = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.popEsi, ptrsToExclude); usableX86Opcodes.popEdi = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.popEdi, ptrsToExclude); usableX86Opcodes.pushad = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.pushad, ptrsToExclude); usableX86Opcodes.incEax = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.incEax, ptrsToExclude); usableX86Opcodes.incEbx = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.incEbx, ptrsToExclude); usableX86Opcodes.incEcx = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.incEcx, ptrsToExclude); usableX86Opcodes.incEdx = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.incEdx, ptrsToExclude); usableX86Opcodes.incEbp = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.incEbp, ptrsToExclude); usableX86Opcodes.incEsp = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.incEsp, ptrsToExclude); usableX86Opcodes.incEsi = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.incEsi, ptrsToExclude); usableX86Opcodes.incEdi = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.incEdi, ptrsToExclude); usableX86Opcodes.decEax = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.decEax, ptrsToExclude); usableX86Opcodes.decEbx = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.decEbx, ptrsToExclude); usableX86Opcodes.decEcx = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.decEcx, ptrsToExclude); usableX86Opcodes.decEdx = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.decEdx, ptrsToExclude); usableX86Opcodes.decEbp = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.decEbp, ptrsToExclude); usableX86Opcodes.decEsp = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.decEsp, ptrsToExclude); usableX86Opcodes.decEsi = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.decEsi, ptrsToExclude); usableX86Opcodes.decEdi = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.decEdi, ptrsToExclude); usableX86Opcodes.add = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.add, ptrsToExclude); usableX86Opcodes.sub = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.sub, ptrsToExclude); usableX86Opcodes.mov = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.mov, ptrsToExclude); usableX86Opcodes.and = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX86Opcodes.and, ptrsToExclude); if (Methods.HasFlag(RopMethod.VirtualAlloc)) { var vpaChain = GenerateVirtualAllocChain32(RcgInfo, startAddress); if (vpaChain.Error == null) { VirtualAllocChain = vpaChain.ReturnValue; } } if (Methods.HasFlag(RopMethod.HeapCreate)) { var hcChain = GenerateHeapCreateChain32(RcgInfo); if (hcChain.Error == null) { HeapCreateChain = hcChain.ReturnValue; } } if (Methods.HasFlag(RopMethod.VirtualProtect)) { var vpChain = GenerateVirtualProtectChain32(RcgInfo); if (vpChain.Error == null) { VirtualProtectChain = vpChain.ReturnValue; } } var output = DisplayOutput.RopChainGadgets32(this); RopChain.ReturnValue = String.Join("\n", output); return RopChain; } /// /// Creates a RopChain for a specific process. /// /// A Address to be used as the start location for which memory will be made executable. /// A list of modules to be excluded from the search for ROP gadgets. /// Enum value representing which methods to build rop chains with. /// Returns an ErcResult string containing public ErcResult GenerateRopChain32(byte[] startAddress = null, List excludes = null, RopMethod methods = RopMethod.All) { Methods = methods; ErcResult RopChain = new ErcResult(RcgInfo.ProcessCore); x86Opcodes = new X86Lists(); var ret1 = GetApiAddresses(RcgInfo); if (ret1.Error != null && ApiAddresses.Count <= 0) { ErcResult failed = new ErcResult(RcgInfo.ProcessCore); failed.ReturnValue = "An error has occured, check log file for more details."; failed.Error = ret1.Error; return failed; } if(excludes != null) { var ret2 = GetRopNops(excludes); if (ret1.Error != null && RopNops.Count <= 0) { ErcResult failed = new ErcResult(RcgInfo.ProcessCore); failed.ReturnValue = "An error has occured, check log file for more details."; failed.Error = ret1.Error; return failed; } } else { var ret2 = GetRopNops(); if (ret1.Error != null && RopNops.Count <= 0) { ErcResult failed = new ErcResult(RcgInfo.ProcessCore); failed.ReturnValue = "An error has occured, check log file for more details."; failed.Error = ret1.Error; return failed; } } var ret3 = PopulateOpcodes(RcgInfo); optimiseLists(RcgInfo); if (Methods.HasFlag(RopMethod.VirtualAlloc)) { var vpaChain = GenerateVirtualAllocChain32(RcgInfo, startAddress); if (vpaChain.Error == null) { VirtualAllocChain = vpaChain.ReturnValue; } } if (Methods.HasFlag(RopMethod.HeapCreate)) { var hcChain = GenerateHeapCreateChain32(RcgInfo); if (hcChain.Error == null) { HeapCreateChain = hcChain.ReturnValue; } } if (Methods.HasFlag(RopMethod.VirtualProtect)) { var vpChain = GenerateVirtualProtectChain32(RcgInfo); if (vpChain.Error == null) { VirtualProtectChain = vpChain.ReturnValue; } } var output = DisplayOutput.RopChainGadgets32(this); RopChain.ReturnValue = String.Join("\n", output); return RopChain; } #endregion #region GetApiAddresses /// /// Gets the handles of 4 functions associated with building ROP chains: VirtualAlloc, HeapCreate, VirtualProtect and WriteProcessMemory /// private ErcResult GetApiAddresses(ProcessInfo info) { ErcResult returnVar = new ErcResult(info.ProcessCore); returnVar.ReturnValue = 0; IntPtr hModule = IntPtr.Zero; for (int i = 0; i < info.ModulesInfo.Count; i++) { if (info.ModulesInfo[i].ModuleName == "kernel32") { hModule = info.ModulesInfo[i].ModuleBase; } } if (info.ProcessMachineType == MachineType.I386 && Environment.Is64BitOperatingSystem) { ApiAddresses.Add("VirtualAlloc", hModule + 0x166B0); ApiAddresses.Add("HeapCreate", hModule + 0x154F0); ApiAddresses.Add("VirtualProtect", hModule + 0x16770); ApiAddresses.Add("WriteProcessMemory", hModule + 0x168B0); return returnVar; } var virtAllocAddress = ErcCore.GetProcAddress(hModule, "VirtualAlloc"); if (virtAllocAddress == IntPtr.Zero) { returnVar.Error = new ERCException(new Win32Exception(Marshal.GetLastWin32Error()).Message); returnVar.LogEvent(); } else { ApiAddresses.Add("VirtualAlloc", virtAllocAddress); } var HeapCreateAddress = ErcCore.GetProcAddress(hModule, "HeapCreate"); if (HeapCreateAddress == IntPtr.Zero) { returnVar.Error = new ERCException(new Win32Exception(Marshal.GetLastWin32Error()).Message); returnVar.LogEvent(); } else { ApiAddresses.Add("HeapCreate", HeapCreateAddress); } var VirtualProtectAddress = ErcCore.GetProcAddress(hModule, "VirtualProtect"); if (VirtualProtectAddress == IntPtr.Zero) { returnVar.Error = new ERCException(new Win32Exception(Marshal.GetLastWin32Error()).Message); returnVar.LogEvent(); } else { ApiAddresses.Add("VirtualProtect", VirtualProtectAddress); } var WriteProcessMemoryAddress = ErcCore.GetProcAddress(hModule, "WriteProcessMemory"); if (WriteProcessMemoryAddress == IntPtr.Zero) { returnVar.Error = new ERCException(new Win32Exception(Marshal.GetLastWin32Error()).Message); returnVar.LogEvent(); } else { ApiAddresses.Add("WriteProcessMemory", WriteProcessMemoryAddress); } return returnVar; } #endregion #region GetRopNops /// /// Gets a list of RopNops from the current process memory. /// /// A list of modules to be excluded from the search /// Returns a ErcResult containing a list of IntPtr private ErcResult> GetRopNops(List excludes = null) { ErcResult> ropNopsResult = new ErcResult>(RcgInfo.ProcessCore); ropNopsResult.ReturnValue = new List(); byte[] ropNop = new byte[] { 0xC3 }; var ropPtrs = RcgInfo.SearchModules(0, searchBytes: ropNop, excludedModules: excludes); if (ropPtrs.Error != null) { ropNopsResult.Error = ropPtrs.Error; } foreach (KeyValuePair k in ropPtrs.ReturnValue) { ropNopsResult.ReturnValue.Add(k.Key); RopNops.Add(k.Key); } return ropNopsResult; } private ErcResult> GetRopNops(ProcessInfo info) { ErcResult> ropNopsResult = new ErcResult>(info.ProcessCore); ropNopsResult.ReturnValue = new List(); byte[] ropNop = new byte[] { 0xC3 }; var ropPtrs = info.SearchModules(0, searchBytes: ropNop); if (ropPtrs.Error != null) { ropNopsResult.Error = ropPtrs.Error; } foreach (KeyValuePair k in ropPtrs.ReturnValue) { ropNopsResult.ReturnValue.Add(k.Key); RopNops.Add(k.Key); } return ropNopsResult; } #endregion #region PopulateOpcodes private ErcResult PopulateOpcodes(ProcessInfo info) { ErcResult ret = new ErcResult(info.ProcessCore); for (int i = 0; i < RopNops.Count; i++) { byte[] bytes = new byte[20]; IntPtr baseAddress = RopNops[i] - 19; ErcCore.ReadProcessMemory(info.ProcessHandle, baseAddress, bytes, 20, out int bytesRead); if (bytesRead != 20) { ret.Error = new ERCException("ReadProcessMemory Error: " + new Win32Exception(Marshal.GetLastWin32Error()).Message); ret.LogEvent(); } var ret1 = ParseByteArrayForRopCodes(bytes, info, baseAddress); if (ret1.Error != null) { ret.Error = ret1.Error; return ret; } } return ret; } #endregion #region ParseByteArrayForRopCodes private ErcResult ParseByteArrayForRopCodes(byte[] bytes, ProcessInfo info, IntPtr baseAddress) { ErcResult ret = new ErcResult(info.ProcessCore); bool pushEaxDone = false; bool pushEbxDone = false; bool pushEcxDone = false; bool pushEdxDone = false; bool pushEspDone = false; bool pushEbpDone = false; bool pushEsiDone = false; bool pushEdiDone = false; bool jmpEspDone = false; bool callEspDone = false; bool xorEaxDone = false; bool xorEbxDone = false; bool xorEcxDone = false; bool xorEdxDone = false; bool xorEsiDone = false; bool xorEdiDone = false; bool popEaxDone = false; bool popEbxDone = false; bool popEcxDone = false; bool popEdxDone = false; bool popEspDone = false; bool popEbpDone = false; bool popEsiDone = false; bool popEdiDone = false; bool pushadDone = false; bool incEaxDone = false; bool incEbxDone = false; bool incEcxDone = false; bool incEdxDone = false; bool incEbpDone = false; bool incEspDone = false; bool incEsiDone = false; bool incEdiDone = false; bool decEaxDone = false; bool decEbxDone = false; bool decEcxDone = false; bool decEdxDone = false; bool decEbpDone = false; bool decEspDone = false; bool decEsiDone = false; bool decEdiDone = false; bool addDone = false; bool subDone = false; bool movDone = false; bool andDone = false; for (int i = bytes.Length - 1; i > 0; i--) { for (int j = 0; j < opcodes32.Count; j++) { if (bytes[i] == opcodes32[j][0] && opcodes32[j].Length == 1) { byte[] opcodes = new byte[bytes.Length - i]; switch (j) { case 0: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x86Opcodes.pushEax.ContainsKey(baseAddress + i) && pushEaxDone == false) { pushEaxDone = true; x86Opcodes.pushEax.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.I386, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 1: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x86Opcodes.pushEbx.ContainsKey(baseAddress + i) && pushEbxDone == false) { pushEbxDone = true; x86Opcodes.pushEbx.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.I386, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 2: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x86Opcodes.pushEcx.ContainsKey(baseAddress + i) && pushEcxDone == false) { pushEcxDone = true; x86Opcodes.pushEcx.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.I386, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 3: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x86Opcodes.pushEdx.ContainsKey(baseAddress + i) && pushEdxDone == false) { pushEdxDone = true; x86Opcodes.pushEdx.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.I386, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 4: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x86Opcodes.pushEsp.ContainsKey(baseAddress + i) && pushEspDone == false) { pushEspDone = true; x86Opcodes.pushEsp.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.I386, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 5: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x86Opcodes.pushEbp.ContainsKey(baseAddress + i) && pushEbpDone == false) { pushEbpDone = true; x86Opcodes.pushEbp.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.I386, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 6: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x86Opcodes.pushEsi.ContainsKey(baseAddress + i) && pushEsiDone == false) { pushEsiDone = true; x86Opcodes.pushEsi.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.I386, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 7: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x86Opcodes.pushEdi.ContainsKey(baseAddress + i) && pushEdiDone == false) { pushEdiDone = true; x86Opcodes.pushEdi.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.I386, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 8: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x86Opcodes.popEax.ContainsKey(baseAddress + i) && popEaxDone == false) { popEaxDone = true; x86Opcodes.popEax.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.I386, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 9: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x86Opcodes.popEbx.ContainsKey(baseAddress + i) && popEbxDone == false) { popEbxDone = true; x86Opcodes.popEbx.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.I386, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 10: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x86Opcodes.popEcx.ContainsKey(baseAddress + i) && popEcxDone == false) { popEcxDone = true; x86Opcodes.popEcx.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.I386, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 11: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x86Opcodes.popEdx.ContainsKey(baseAddress + i) && popEdxDone == false) { popEdxDone = true; x86Opcodes.popEdx.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.I386, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 12: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x86Opcodes.popEsp.ContainsKey(baseAddress + i) && popEspDone == false) { popEspDone = true; x86Opcodes.popEsp.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.I386, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 13: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x86Opcodes.popEbp.ContainsKey(baseAddress + i) && popEbpDone == false) { popEbpDone = true; x86Opcodes.popEbp.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.I386, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 14: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x86Opcodes.popEsi.ContainsKey(baseAddress + i) && popEsiDone == false) { popEsiDone = true; x86Opcodes.popEsi.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.I386, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 15: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x86Opcodes.popEdi.ContainsKey(baseAddress + i) && popEdiDone == false) { popEdiDone = true; x86Opcodes.popEdi.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.I386, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 16: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x86Opcodes.pushad.ContainsKey(baseAddress + i) && pushadDone == false) { pushadDone = true; x86Opcodes.pushad.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.I386, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 17: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x86Opcodes.incEax.ContainsKey(baseAddress + i) && incEaxDone == false) { incEaxDone = true; x86Opcodes.incEax.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.I386, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 18: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x86Opcodes.incEbx.ContainsKey(baseAddress + i) && incEbxDone == false) { incEbxDone = true; x86Opcodes.incEbx.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.I386, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 19: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x86Opcodes.incEcx.ContainsKey(baseAddress + i) && incEcxDone == false) { incEcxDone = true; x86Opcodes.incEcx.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.I386, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 20: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x86Opcodes.incEdx.ContainsKey(baseAddress + i) && incEdxDone == false) { incEdxDone = true; x86Opcodes.incEdx.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.I386, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 21: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x86Opcodes.incEbp.ContainsKey(baseAddress + i) && incEbpDone == false) { incEbpDone = true; x86Opcodes.incEbp.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.I386, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 22: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x86Opcodes.incEsp.ContainsKey(baseAddress + i) && incEspDone == false) { incEspDone = true; x86Opcodes.incEsp.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.I386, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 23: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x86Opcodes.incEsi.ContainsKey(baseAddress + i) && incEsiDone == false) { incEsiDone = true; x86Opcodes.incEsi.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.I386, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 24: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x86Opcodes.incEdi.ContainsKey(baseAddress + i) && incEdiDone == false) { incEdiDone = true; x86Opcodes.incEdi.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.I386, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 25: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x86Opcodes.decEax.ContainsKey(baseAddress + i) && decEaxDone == false) { decEaxDone = true; x86Opcodes.decEax.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.I386, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 26: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x86Opcodes.decEbx.ContainsKey(baseAddress + i) && decEbxDone == false) { decEbxDone = true; x86Opcodes.decEbx.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.I386, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 27: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x86Opcodes.decEcx.ContainsKey(baseAddress + i) && decEcxDone == false) { decEcxDone = true; x86Opcodes.decEcx.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.I386, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 28: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x86Opcodes.decEdx.ContainsKey(baseAddress + i) && decEdxDone == false) { decEdxDone = true; x86Opcodes.decEdx.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.I386, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 29: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x86Opcodes.decEbp.ContainsKey(baseAddress + i) && decEbpDone == false) { decEbpDone = true; x86Opcodes.decEbp.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.I386, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 30: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x86Opcodes.decEsp.ContainsKey(baseAddress + i) && decEspDone == false) { decEspDone = true; x86Opcodes.decEsp.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.I386, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 31: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x86Opcodes.decEsi.ContainsKey(baseAddress + i) && decEsiDone == false) { decEsiDone = true; x86Opcodes.decEsi.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.I386, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 32: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x86Opcodes.decEdi.ContainsKey(baseAddress + i) && decEdiDone == false) { decEdiDone = true; x86Opcodes.decEdi.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.I386, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 41: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x86Opcodes.add.ContainsKey(baseAddress + i) && addDone == false) { addDone = true; x86Opcodes.add.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.I386, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 42: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x86Opcodes.sub.ContainsKey(baseAddress + i) && subDone == false) { subDone = true; x86Opcodes.sub.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.I386, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 43: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x86Opcodes.mov.ContainsKey(baseAddress + i) && movDone == false) { movDone = true; x86Opcodes.mov.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.I386, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 44: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x86Opcodes.and.ContainsKey(baseAddress + i) && andDone == false) { andDone = true; x86Opcodes.and.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.I386, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; default: throw new ERCException("An error has occured in RopChainGenerator.ParseByteArrayForRopCodes whilst parsing single length x86 instructions"); } } else if (opcodes32[j].Length > 1) { if (bytes[i] == opcodes32[j][0] && i < bytes.Length - 1 && j < opcodes32.Count + 1 && bytes[i + 1] == opcodes32[j][1]) { byte[] opcodes = new byte[bytes.Length - i]; switch (j) { case 33: opcodes = new byte[2]; Array.Copy(bytes, i, opcodes, 0, 2); if (!x86Opcodes.jmpEsp.ContainsKey(baseAddress + i) && jmpEspDone == false) { jmpEspDone = true; x86Opcodes.jmpEsp.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.I386, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 34: opcodes = new byte[2]; Array.Copy(bytes, i, opcodes, 0, 2); if (!x86Opcodes.callEsp.ContainsKey(baseAddress + i) && callEspDone == false) { callEspDone = true; x86Opcodes.callEsp.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.I386, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 35: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x86Opcodes.xorEax.ContainsKey(baseAddress + i) && xorEaxDone == false) { xorEaxDone = true; x86Opcodes.xorEax.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.I386, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 36: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x86Opcodes.xorEbx.ContainsKey(baseAddress + i) && xorEbxDone == false) { xorEbxDone = true; x86Opcodes.xorEbx.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.I386, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 37: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x86Opcodes.xorEcx.ContainsKey(baseAddress + i) && xorEcxDone == false) { xorEcxDone = true; x86Opcodes.xorEcx.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.I386, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 38: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x86Opcodes.xorEdx.ContainsKey(baseAddress + i) && xorEdxDone == false) { xorEdxDone = true; x86Opcodes.xorEdx.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.I386, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 39: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x86Opcodes.xorEsi.ContainsKey(baseAddress + i) && xorEsiDone == false) { xorEsiDone = true; x86Opcodes.xorEsi.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.I386, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 40: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x86Opcodes.xorEdi.ContainsKey(baseAddress + i) && xorEdiDone == false) { xorEdiDone = true; x86Opcodes.xorEdi.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.I386, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; default: throw new ERCException("An error has occured in RopChainGenerator.ParseByteArrayForRopCodes whilst parsing double length x86 instructions"); } } } } } return ret; } #endregion #region Optimse Lists private void optimiseLists(ProcessInfo info) { usableX86Opcodes = new X86Lists(); var thisList = x86Opcodes.pushEax.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("push eax") || !thisList[i].Value.Contains("ret") || thisList[i].Value.Any(char.IsDigit)) { thisList.RemoveAt(i); } else { usableX86Opcodes.pushEax.Add(thisList[i].Key, thisList[i].Value); } } thisList = x86Opcodes.pushEbx.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("push ebx") || !thisList[i].Value.Contains("ret") || thisList[i].Value.Any(char.IsDigit)) { thisList.RemoveAt(i); } else { usableX86Opcodes.pushEbx.Add(thisList[i].Key, thisList[i].Value); } } thisList = x86Opcodes.pushEcx.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("push ecx") || !thisList[i].Value.Contains("ret") || thisList[i].Value.Any(char.IsDigit)) { thisList.RemoveAt(i); } else { usableX86Opcodes.pushEcx.Add(thisList[i].Key, thisList[i].Value); } } thisList = x86Opcodes.pushEdx.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("push edx") || !thisList[i].Value.Contains("ret") || thisList[i].Value.Any(char.IsDigit)) { thisList.RemoveAt(i); } else { usableX86Opcodes.pushEdx.Add(thisList[i].Key, thisList[i].Value); } } thisList = x86Opcodes.pushEsp.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("push esp") || !thisList[i].Value.Contains("ret") || thisList[i].Value.Any(char.IsDigit)) { thisList.RemoveAt(i); } else { usableX86Opcodes.pushEsp.Add(thisList[i].Key, thisList[i].Value); } } thisList = x86Opcodes.pushEbp.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("push ebp") || !thisList[i].Value.Contains("ret") || thisList[i].Value.Any(char.IsDigit)) { thisList.RemoveAt(i); } else { usableX86Opcodes.pushEbp.Add(thisList[i].Key, thisList[i].Value); } } thisList = x86Opcodes.pushEsi.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("push esi") || !thisList[i].Value.Contains("ret") || thisList[i].Value.Any(char.IsDigit)) { thisList.RemoveAt(i); } else { usableX86Opcodes.pushEsi.Add(thisList[i].Key, thisList[i].Value); } } thisList = x86Opcodes.pushEdi.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("push edi") || !thisList[i].Value.Contains("ret") || thisList[i].Value.Any(char.IsDigit)) { thisList.RemoveAt(i); } else { usableX86Opcodes.pushEdi.Add(thisList[i].Key, thisList[i].Value); } } thisList = x86Opcodes.jmpEsp.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("jmp esp")) { thisList.RemoveAt(i); } else { usableX86Opcodes.jmpEsp.Add(thisList[i].Key, thisList[i].Value); } } thisList = x86Opcodes.callEsp.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("call esp")) { thisList.RemoveAt(i); } else { usableX86Opcodes.callEsp.Add(thisList[i].Key, thisList[i].Value); } } thisList = x86Opcodes.xorEax.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("xor eax") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX86Opcodes.xorEax.Add(thisList[i].Key, thisList[i].Value); } } thisList = x86Opcodes.xorEbx.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("xor ebx") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX86Opcodes.xorEbx.Add(thisList[i].Key, thisList[i].Value); } } thisList = x86Opcodes.xorEcx.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("xor ecx") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX86Opcodes.xorEcx.Add(thisList[i].Key, thisList[i].Value); } } thisList = x86Opcodes.xorEdx.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("xor edx") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX86Opcodes.xorEdx.Add(thisList[i].Key, thisList[i].Value); } } thisList = x86Opcodes.xorEsi.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("xor esi") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX86Opcodes.xorEsi.Add(thisList[i].Key, thisList[i].Value); } } thisList = x86Opcodes.xorEdi.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("xor edi") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX86Opcodes.xorEdi.Add(thisList[i].Key, thisList[i].Value); } } thisList = x86Opcodes.popEax.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("pop eax") || !thisList[i].Value.Contains("ret") || thisList[i].Value.Any(char.IsDigit)) { thisList.RemoveAt(i); } else { usableX86Opcodes.popEax.Add(thisList[i].Key, thisList[i].Value); } } thisList = x86Opcodes.popEbx.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("pop ebx") || !thisList[i].Value.Contains("ret") || thisList[i].Value.Any(char.IsDigit)) { thisList.RemoveAt(i); } else { usableX86Opcodes.popEbx.Add(thisList[i].Key, thisList[i].Value); } } thisList = x86Opcodes.popEcx.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("pop ecx") || !thisList[i].Value.Contains("ret") || thisList[i].Value.Any(char.IsDigit)) { thisList.RemoveAt(i); } else { usableX86Opcodes.popEcx.Add(thisList[i].Key, thisList[i].Value); } } thisList = x86Opcodes.popEdx.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("pop edx") || !thisList[i].Value.Contains("ret") || thisList[i].Value.Any(char.IsDigit)) { thisList.RemoveAt(i); } else { usableX86Opcodes.popEdx.Add(thisList[i].Key, thisList[i].Value); } } thisList = x86Opcodes.popEsp.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("pop esp") || !thisList[i].Value.Contains("ret") || thisList[i].Value.Any(char.IsDigit)) { thisList.RemoveAt(i); } else { usableX86Opcodes.popEsp.Add(thisList[i].Key, thisList[i].Value); } } thisList = x86Opcodes.popEbp.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("pop ebp") || !thisList[i].Value.Contains("ret") || thisList[i].Value.Any(char.IsDigit)) { thisList.RemoveAt(i); } else { usableX86Opcodes.popEbp.Add(thisList[i].Key, thisList[i].Value); } } thisList = x86Opcodes.popEsi.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("pop esi") || !thisList[i].Value.Contains("ret") || thisList[i].Value.Any(char.IsDigit)) { thisList.RemoveAt(i); } else { usableX86Opcodes.popEsi.Add(thisList[i].Key, thisList[i].Value); } } thisList = x86Opcodes.popEdi.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("pop edi") || !thisList[i].Value.Contains("ret") || thisList[i].Value.Any(char.IsDigit)) { thisList.RemoveAt(i); } else { usableX86Opcodes.popEdi.Add(thisList[i].Key, thisList[i].Value); } } thisList = x86Opcodes.pushad.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("pushad") || !thisList[i].Value.Contains("ret") || thisList[i].Value.Any(char.IsDigit)) { thisList.RemoveAt(i); } else { usableX86Opcodes.pushad.Add(thisList[i].Key, thisList[i].Value); } } thisList = x86Opcodes.incEax.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("inc eax") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX86Opcodes.incEax.Add(thisList[i].Key, thisList[i].Value); } } thisList = x86Opcodes.incEbx.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("inc ebx") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX86Opcodes.incEbx.Add(thisList[i].Key, thisList[i].Value); } } thisList = x86Opcodes.incEcx.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("inc ecx") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX86Opcodes.incEcx.Add(thisList[i].Key, thisList[i].Value); } } thisList = x86Opcodes.incEdx.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("inc edx") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX86Opcodes.incEdx.Add(thisList[i].Key, thisList[i].Value); } } thisList = x86Opcodes.incEbp.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("inc ebp") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX86Opcodes.incEbp.Add(thisList[i].Key, thisList[i].Value); } } thisList = x86Opcodes.incEsp.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("inc esp") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX86Opcodes.incEsp.Add(thisList[i].Key, thisList[i].Value); } } thisList = x86Opcodes.incEsi.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("inc esi") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX86Opcodes.incEsi.Add(thisList[i].Key, thisList[i].Value); } } thisList = x86Opcodes.incEdi.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("inc edi") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX86Opcodes.incEdi.Add(thisList[i].Key, thisList[i].Value); } } thisList = x86Opcodes.decEax.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("dec eax") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX86Opcodes.decEax.Add(thisList[i].Key, thisList[i].Value); } } thisList = x86Opcodes.decEbx.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("dec ebx") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX86Opcodes.decEbx.Add(thisList[i].Key, thisList[i].Value); } } thisList = x86Opcodes.decEcx.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("dec ecx") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX86Opcodes.decEcx.Add(thisList[i].Key, thisList[i].Value); } } thisList = x86Opcodes.decEdx.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("dec edx") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX86Opcodes.decEdx.Add(thisList[i].Key, thisList[i].Value); } } thisList = x86Opcodes.decEbp.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("dec ebp") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX86Opcodes.decEbp.Add(thisList[i].Key, thisList[i].Value); } } thisList = x86Opcodes.decEsp.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("dec esp") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX86Opcodes.decEsp.Add(thisList[i].Key, thisList[i].Value); } } thisList = x86Opcodes.decEsi.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("dec esi") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX86Opcodes.decEsi.Add(thisList[i].Key, thisList[i].Value); } } thisList = x86Opcodes.decEdi.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("dec edi") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX86Opcodes.decEdi.Add(thisList[i].Key, thisList[i].Value); } } thisList = x86Opcodes.add.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("add") || !thisList[i].Value.Contains("ret") || thisList[i].Value.Any(char.IsDigit)) { thisList.RemoveAt(i); } else { usableX86Opcodes.add.Add(thisList[i].Key, thisList[i].Value); } } thisList = x86Opcodes.sub.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("sub") || !thisList[i].Value.Contains("ret") || thisList[i].Value.Any(char.IsDigit)) { thisList.RemoveAt(i); } else { usableX86Opcodes.sub.Add(thisList[i].Key, thisList[i].Value); } } thisList = x86Opcodes.mov.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("mov") || !thisList[i].Value.Contains("ret") || thisList[i].Value.Any(char.IsDigit)) { thisList.RemoveAt(i); } else { usableX86Opcodes.mov.Add(thisList[i].Key, thisList[i].Value); } } thisList = x86Opcodes.and.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("and") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX86Opcodes.and.Add(thisList[i].Key, thisList[i].Value); } } } #endregion #region GenerateVirtualAllocChain32 private ErcResult>> GenerateVirtualAllocChain32(ProcessInfo info, byte[] startAddress = null) { //////////////////////////////////////////////////////////////// // VirtualAlloc Template: // // EAX: 90909090 -> Nop sled // // ECX: 00000040 -> flProtect // // EDX: 00001000 -> flAllocationType // // EBX: ???????? -> Int size (area to be set as executable) // // ESP: ???????? -> No Change // // EBP: ???????? -> Jmp Esp / Call Esp // // ESI: ???????? -> ApiAddresses["VirtualAlloc"] // // EDI: ???????? -> RopNop // // // // + place ptr to "jmp esp" on stack, below PUSHAD // //////////////////////////////////////////////////////////////// ErcResult>> VirtualAlloc = new ErcResult>>(info.ProcessCore); VirtualAlloc.ReturnValue = new List>(); Register32 regState32 = new Register32(); regState32 |= Register32.ESP; RegisterModifiers32 regModified32 = new RegisterModifiers32(); foreach (Register32 i in Enum.GetValues(typeof(Register32))) { SetRegisterModifier(regModified32.ESP, i, regModified32); SetRegisterModifier(i, regModified32.ESP, regModified32); } RegisterLists32 regLists32 = new RegisterLists32(); while (!CompleteRegisters32(regState32)) { byte[] nulls = new byte[] { 0x00, 0x00, 0x00, 0x00 }; #region Populate EDI if (!regState32.HasFlag(Register32.EDI)) { regLists32.ediList = null; regLists32.ediList = new List>(); for (int i = 0; i < usableX86Opcodes.popEdi.Count; i++) { if (!regState32.HasFlag(Register32.EDI)) { if (usableX86Opcodes.popEdi.ElementAt(i).Value.Length <= 14 && !usableX86Opcodes.popEdi.ElementAt(i).Value.Contains("invalid")) { regLists32.ediList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(BitConverter.GetBytes((long)RopNops[0])), "ROP NOP")); regLists32.ediList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(BitConverter.GetBytes((long)usableX86Opcodes.popEdi.ElementAt(i).Key)), usableX86Opcodes.popEdi.ElementAt(i).Value)); regState32 |= Register32.EDI; } } else { i = usableX86Opcodes.popEdi.Count; } } foreach (Register32 i in Enum.GetValues(typeof(Register32))) { if (!regState32.HasFlag(Register32.EDI)) { var popInstruction = GetPopInstruction(Register32.EDI, i, regModified32); if (popInstruction != null) { var movInstruction = GetMovInstruction(Register32.EDI, i); if (movInstruction != null) { regLists32.ediList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(BitConverter.GetBytes((long)RopNops[0])), "ROP NOP")); regLists32.ediList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(movInstruction.Item1), movInstruction.Item2)); regLists32.ediList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(popInstruction.Item1), popInstruction.Item2)); SetRegisterModifier(Register32.EDI, i, regModified32); regState32 &= ~i; regState32 |= Register32.EDI; } } } else { break; } } if (!regState32.HasFlag(Register32.EDI)) { regLists32.ediList = null; regLists32.ediList = new List>(); byte[] nullBytes = new byte[] { 0x00, 0x00, 0x00, 0x00 }; regLists32.ediList.Add(Tuple.Create(nullBytes, "Unable to find appropriate instruction. EDI must be allocated manually")); regState32 |= Register32.EDI; } } #endregion #region Populate ESI if (!regState32.HasFlag(Register32.ESI)) { regLists32.esiList = null; regLists32.esiList = new List>(); for (int i = 0; i < usableX86Opcodes.popEsi.Count; i++) { if (!regState32.HasFlag(Register32.ESI)) { if (usableX86Opcodes.popEsi.ElementAt(i).Value.Length <= 14 && !usableX86Opcodes.popEsi.ElementAt(i).Value.Contains("invalid")) { regLists32.esiList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(BitConverter.GetBytes((long)ApiAddresses["VirtualAlloc"])), "Pointer to VirtualAlloc.")); regLists32.esiList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(BitConverter.GetBytes((long)usableX86Opcodes.popEsi.ElementAt(i).Key)), usableX86Opcodes.popEsi.ElementAt(i).Value)); regState32 |= Register32.ESI; } } else { i = usableX86Opcodes.popEsi.Count; } } if (!regState32.HasFlag(Register32.ESI)) { foreach (Register32 i in Enum.GetValues(typeof(Register32))) { if (!regState32.HasFlag(Register32.ESI)) { var popInstruction = GetPopInstruction(Register32.ESI, i, regModified32); if (popInstruction != null) { var movInstruction = GetMovInstruction(Register32.ESI, i); if (movInstruction != null) { regLists32.esiList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(BitConverter.GetBytes((long)ApiAddresses["VirtualAlloc"])), "Pointer to VirtualAlloc.")); regLists32.esiList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(popInstruction.Item1), popInstruction.Item2)); regLists32.esiList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(movInstruction.Item1), movInstruction.Item2)); SetRegisterModifier(Register32.ESI, i, regModified32); regState32 &= ~i; regState32 |= Register32.ESI; } } } } if (!regState32.HasFlag(Register32.ESI)) { regLists32.esiList = null; regLists32.esiList = new List>(); byte[] nullBytes = new byte[] { 0x00, 0x00, 0x00, 0x00 }; regLists32.esiList.Add(Tuple.Create(nullBytes, "Unable to find appropriate instruction. ESI must be allocated manually")); regState32 |= Register32.ESI; } } } #endregion #region Populate EBP if (!regState32.HasFlag(Register32.EBP)) { regLists32.ebpList = null; regLists32.ebpList = new List>(); for (int i = 0; i < usableX86Opcodes.popEbp.Count; i++) { if (!regState32.HasFlag(Register32.EBP)) { if (usableX86Opcodes.popEbp.ElementAt(i).Value.Length <= 14 && !usableX86Opcodes.popEbp.ElementAt(i).Value.Contains("invalid")) { regLists32.ebpList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(BitConverter.GetBytes((long)usableX86Opcodes.popEbp.ElementAt(i).Key)), usableX86Opcodes.popEbp.ElementAt(i).Value)); if (startAddress != null) { regLists32.ebpList.Add(Tuple.Create(startAddress, "User supplied start address")); } else { if (usableX86Opcodes.jmpEsp.Count > 0) { regLists32.ebpList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(BitConverter.GetBytes((long)usableX86Opcodes.jmpEsp.ElementAt(0).Key)), usableX86Opcodes.jmpEsp.ElementAt(0).Value)); } else { regLists32.ebpList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(BitConverter.GetBytes((long)usableX86Opcodes.callEsp.ElementAt(0).Key)), usableX86Opcodes.callEsp.ElementAt(0).Value)); } } regState32 |= Register32.EBP; } } else { i = usableX86Opcodes.popEbp.Count; } } if (!regState32.HasFlag(Register32.EBP)) { foreach (Register32 i in Enum.GetValues(typeof(Register32))) { if (!regState32.HasFlag(Register32.EBP)) { var popInstruction = GetPopInstruction(Register32.EBP, i, regModified32); if (popInstruction != null) { var movInstruction = GetMovInstruction(Register32.EBP, i); if (movInstruction != null) { if (usableX86Opcodes.jmpEsp.Count > 0) { regLists32.ebpList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(BitConverter.GetBytes((long)usableX86Opcodes.jmpEsp.ElementAt(0).Key)), usableX86Opcodes.jmpEsp.ElementAt(0).Value)); } else { regLists32.ebpList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(BitConverter.GetBytes((long)usableX86Opcodes.callEsp.ElementAt(0).Key)), usableX86Opcodes.callEsp.ElementAt(0).Value)); } regLists32.ebpList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(popInstruction.Item1), popInstruction.Item2)); regLists32.ebpList.Add(Tuple.Create(movInstruction.Item1, movInstruction.Item2)); SetRegisterModifier(Register32.EBP, i, regModified32); regState32 &= ~i; regState32 |= Register32.EBP; } } } } if (!regState32.HasFlag(Register32.EBP)) { regLists32.ebpList = null; regLists32.ebpList = new List>(); byte[] nullBytes = new byte[] { 0x00, 0x00, 0x00, 0x00 }; regLists32.ebpList.Add(Tuple.Create(nullBytes, "Unable to find appropriate instruction. EBP must be allocated manually")); regState32 |= Register32.EBP; } } } #endregion #region Populate EBX // Populate EBX if (!regState32.HasFlag(Register32.EBX)) { regLists32.ebxList = null; regLists32.ebxList = new List>(); var xorEbx = GetXorInstruction(Register32.EBX); if (xorEbx != null) { regLists32.ebxList.Add(Tuple.Create(xorEbx.Item1, xorEbx.Item2)); if (usableX86Opcodes.incEbx.Count > 0) { if (usableX86Opcodes.incEbx.ElementAt(0).Value.Length <= 14) { regLists32.ebxList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(BitConverter.GetBytes((long)usableX86Opcodes.incEbx.ElementAt(0).Key)), usableX86Opcodes.incEbx.ElementAt(0).Value)); regState32 |= Register32.EBX; } } } if (!regState32.HasFlag(Register32.EBX)) { var zeroEbx = ZeroRegister(Register32.EBX, regModified32); if (zeroEbx != null && usableX86Opcodes.incEbx.Count > 0 && usableX86Opcodes.incEbx.ElementAt(0).Value.Length <= 14) { for (int i = 0; i < zeroEbx.Count; i++) { regLists32.ebxList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(zeroEbx[i].Item1), zeroEbx[i].Item2)); } regLists32.ebxList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier( BitConverter.GetBytes((long)usableX86Opcodes.incEbx.ElementAt(0).Key)), usableX86Opcodes.incEbx.ElementAt(0).Value)); SetRegisterModifier(Register32.EBX, zeroEbx[0].Item3, regModified32); regState32 &= ~zeroEbx[0].Item3; regState32 |= Register32.EBX; } } if (!regState32.HasFlag(Register32.EBX)) { foreach(Register32 i in Enum.GetValues(typeof(Register32))) { var popInstruction = GetPopInstruction(Register32.EBX, i, regModified32); if (popInstruction != null) { for (int j = 0; j < x86Opcodes.add.Count; j++) { if (!regState32.HasFlag(Register32.EBX)) { var strings = x86Opcodes.add.ElementAt(j).Value.Split(','); if (strings[0].Contains(" ebx") && strings[1].Contains(i.ToString().ToLower())) { regLists32.ebxList.Add(Tuple.Create(popInstruction.Item1, popInstruction.Item2)); byte[] bytes = new byte[] { 0xFF, 0xFF, 0xFF, 0xFF };//......................................replace this with a more long term solution. Dynamically allocate size based on the size category in regLists32.ebxList.Add(Tuple.Create(bytes, "To be popped into " + i.ToString())); regLists32.ebxList.Add(Tuple.Create(BitConverter.GetBytes((long)x86Opcodes.add.ElementAt(j).Key), x86Opcodes.add.ElementAt(j).Value)); regLists32.ebxList.Add(Tuple.Create(popInstruction.Item1, popInstruction.Item2)); bytes = new byte[] { 0x01, 0x01, 0x10, 0x01 };//......................................replace this with a more long term solution. Dynamically allocate size based on the size category in regLists32.ebxList.Add(Tuple.Create(bytes, "To be popped into " + i.ToString())); regLists32.ebxList.Add(Tuple.Create(BitConverter.GetBytes((long)x86Opcodes.add.ElementAt(j).Key), x86Opcodes.add.ElementAt(j).Value)); SetRegisterModifier(Register32.EBX, i, regModified32); regState32 &= ~i; regState32 |= Register32.EBX; } } } } } } } if (!regState32.HasFlag(Register32.EBX)) { regLists32.ebxList = null; regLists32.ebxList = new List>(); byte[] nullBytes = new byte[] { 0x00, 0x00, 0x00, 0x00 }; regLists32.ebxList.Add(Tuple.Create(nullBytes, "Unable to find appropriate instruction. EBX must be allocated manually")); regState32 |= Register32.EBX; } #endregion #region Populate EDX if (!regState32.HasFlag(Register32.EDX)) { regLists32.edxList = null; regLists32.edxList = new List>(); var xorEDX = GetXorInstruction(Register32.EDX); if(xorEDX != null) { foreach(Register32 i in Enum.GetValues(typeof(Register32))) { if (!regState32.HasFlag(Register32.EDX)) { var popInstruction = GetPopInstruction(Register32.EDX, i, regModified32); if (popInstruction != null) { var addInstruction = GetAddInstruction(Register32.EDX, i); if (addInstruction != null) { byte[] add1 = new byte[] { 0xFF, 0xFF, 0xFF, 0xFF }; byte[] add2 = new byte[] { 0x01, 0x11, 0x01, 0x01 }; regLists32.edxList.Add(Tuple.Create(xorEDX.Item1, xorEDX.Item2)); regLists32.edxList.Add(Tuple.Create(add1, "To be placed into " + addInstruction.Item3.ToString())); regLists32.edxList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(popInstruction.Item1), popInstruction.Item2)); regLists32.edxList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(addInstruction.Item1), addInstruction.Item2)); regLists32.edxList.Add(Tuple.Create(add2, "To be placed into " + addInstruction.Item3.ToString() + " combined = 0x00001000")); regLists32.edxList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(popInstruction.Item1), popInstruction.Item2)); regLists32.edxList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(addInstruction.Item1), addInstruction.Item2)); SetRegisterModifier(Register32.EDX, i, regModified32); regState32 &= ~i; regState32 |= Register32.EDX; } } } } } if (!regState32.HasFlag(Register32.EDX)) { foreach (Register32 i in Enum.GetValues(typeof(Register32))) { if (!regState32.HasFlag(Register32.EDX)) { var popInstruction = GetPopInstruction(Register32.EDX, i, regModified32); if (popInstruction != null) { foreach(Register32 j in Enum.GetValues(typeof(Register32))) { if (!regState32.HasFlag(Register32.EDX) && i != j) { var popInstruction2 = GetPopInstruction(Register32.EDX, j, regModified32); if (popInstruction2 != null) { var addInstruction = GetAddInstruction(i, j); if (addInstruction != null) { var movInstruction = GetMovInstruction(Register32.EDX, i); if (movInstruction != null) { byte[] add1 = new byte[] { 0xFF, 0xFF, 0xFF, 0xFF }; byte[] add2 = new byte[] { 0x01, 0x11, 0x01, 0x01 }; regLists32.edxList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(popInstruction.Item1), popInstruction.Item2)); regLists32.edxList.Add(Tuple.Create(add1, "To be placed into " + popInstruction.Item3.ToString())); regLists32.edxList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(popInstruction2.Item1), popInstruction2.Item2)); regLists32.edxList.Add(Tuple.Create(add2, "To be placed into " + addInstruction.Item3.ToString() + " combined = 0x00001000")); regLists32.edxList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(addInstruction.Item1), addInstruction.Item2)); regLists32.edxList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(movInstruction.Item1), movInstruction.Item2)); SetRegisterModifier(Register32.EDX, i, regModified32); SetRegisterModifier(Register32.EDX, j, regModified32); regState32 &= ~i; regState32 &= ~j; regState32 |= Register32.EDX; } } } } } } } } } if (!regState32.HasFlag(Register32.EDX)) { regLists32.edxList = null; regLists32.edxList = new List>(); byte[] nullBytes = new byte[] { 0x00, 0x00, 0x00, 0x00 }; regLists32.edxList.Add(Tuple.Create(nullBytes, "Unable to find appropriate instruction. EDX must be allocated manually")); regState32 |= Register32.EDX; } } #endregion #region Populate ECX if (!regState32.HasFlag(Register32.ECX)) { regLists32.ecxList = null; regLists32.ecxList = new List>(); var xorECX = GetXorInstruction(Register32.ECX); if (xorECX != null) { foreach (Register32 i in Enum.GetValues(typeof(Register32))) { if (!regState32.HasFlag(Register32.ECX)) { var popInstruction = GetPopInstruction(Register32.ECX, i, regModified32); if (popInstruction != null) { var addInstruction = GetAddInstruction(Register32.ECX, i); if (addInstruction != null) { byte[] add1 = new byte[] { 0xFF, 0xFF, 0xFF, 0xFF }; byte[] add2 = new byte[] { 0x01, 0x11, 0x01, 0x01 }; regLists32.ecxList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(xorECX.Item1), xorECX.Item2)); regLists32.ecxList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(popInstruction.Item1), popInstruction.Item2)); regLists32.ecxList.Add(Tuple.Create(add1, "To be placed into " + addInstruction.Item3.ToString())); regLists32.ecxList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(addInstruction.Item1), addInstruction.Item2)); regLists32.ecxList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(popInstruction.Item1), popInstruction.Item2)); regLists32.ecxList.Add(Tuple.Create(add2, "To be placed into " + addInstruction.Item3.ToString() + " combined = 0x00000040")); regLists32.ecxList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(addInstruction.Item1), addInstruction.Item2)); SetRegisterModifier(Register32.ECX, i, regModified32); regState32 &= ~i; regState32 |= Register32.ECX; } } } } } if (!regState32.HasFlag(Register32.ECX)) { foreach (Register32 i in Enum.GetValues(typeof(Register32))) { if (!regState32.HasFlag(Register32.ECX)) { var popInstruction = GetPopInstruction(Register32.ECX, i, regModified32); if (popInstruction != null) { foreach (Register32 j in Enum.GetValues(typeof(Register32))) { if (!regState32.HasFlag(Register32.ECX) && i != j) { var popInstruction2 = GetPopInstruction(Register32.ECX, j, regModified32); if (popInstruction2 != null) { var addInstruction = GetAddInstruction(i, j); if (addInstruction != null) { var movInstruction = GetMovInstruction(Register32.ECX, i); if (movInstruction != null) { byte[] add1 = new byte[] { 0xFF, 0xFF, 0xFF, 0xFF }; byte[] add2 = new byte[] { 0x41, 0x01, 0x01, 0x01 }; regLists32.ecxList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(popInstruction.Item1), popInstruction.Item2)); regLists32.ecxList.Add(Tuple.Create(add1, "To be placed into " + popInstruction.Item3.ToString())); regLists32.ecxList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(popInstruction2.Item1), popInstruction2.Item2)); regLists32.ecxList.Add(Tuple.Create(add2, "To be placed into " + addInstruction.Item3.ToString() + " combined = 0x00000040")); regLists32.ecxList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(addInstruction.Item1), addInstruction.Item2)); regLists32.ecxList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(movInstruction.Item1), movInstruction.Item2)); SetRegisterModifier(Register32.ECX, i, regModified32); SetRegisterModifier(Register32.ECX, j, regModified32); regState32 &= ~i; regState32 &= ~j; regState32 |= Register32.ECX; } } } } } } } } } if (!regState32.HasFlag(Register32.ECX)) { regLists32.edxList = null; regLists32.edxList = new List>(); byte[] nullBytes = new byte[] { 0x00, 0x00, 0x00, 0x00 }; regLists32.edxList.Add(Tuple.Create(nullBytes, "Unable to find appropriate instruction. EDX must be allocated manually")); regState32 |= Register32.ECX; } } #endregion #region Populate EAX if (!regState32.HasFlag(Register32.EAX)) { byte[] nops = new byte[] { 0x90, 0x90, 0x90, 0x90 }; regLists32.eaxList = null; regLists32.eaxList = new List>(); for (int i = 0; i < usableX86Opcodes.popEax.Count; i++) { if (!regState32.HasFlag(Register32.EAX)) { if (usableX86Opcodes.popEax.ElementAt(i).Value.Length <= 14 && !usableX86Opcodes.popEax.ElementAt(i).Value.Contains("invalid")) { regLists32.eaxList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(BitConverter.GetBytes((long)usableX86Opcodes.popEax.ElementAt(i).Key)), usableX86Opcodes.popEax.ElementAt(i).Value)); regLists32.eaxList.Add(Tuple.Create(nops, "NOPS")); regState32 |= Register32.EAX; } } else { i = usableX86Opcodes.popEax.Count; } } foreach (Register32 i in Enum.GetValues(typeof(Register32))) { if (!regState32.HasFlag(Register32.EAX)) { var popInstruction = GetPopInstruction(Register32.EAX, i, regModified32); if (popInstruction != null) { var movInstruction = GetMovInstruction(Register32.EAX, i); if (movInstruction != null) { regLists32.eaxList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(popInstruction.Item1), popInstruction.Item2)); regLists32.eaxList.Add(Tuple.Create(nops, "NOPS")); regLists32.eaxList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(movInstruction.Item1), movInstruction.Item2)); SetRegisterModifier(Register32.EAX, i, regModified32); regState32 &= ~i; regState32 |= Register32.EAX; } } } else { break; } } if (!regState32.HasFlag(Register32.EAX)) { regLists32.eaxList = null; regLists32.eaxList = new List>(); byte[] nullBytes = new byte[] { 0x00, 0x00, 0x00, 0x00 }; regLists32.eaxList.Add(Tuple.Create(nullBytes, "Unable to find appropriate instruction. EAX must be allocated manually")); regState32 |= Register32.EAX; } } #endregion } VirtualAlloc.ReturnValue = BuildRopChain(regLists32, regModified32, true); return VirtualAlloc; } #endregion #region GenerateHeapCreateChain32 private ErcResult>> GenerateHeapCreateChain32(ProcessInfo info) { //////////////////////////////////////////////////////////////// // HeapCreate Template: // // EAX: 90909090 -> Nop sled // // ECX: 00010000 -> dwMaximumSize // // EDX: 00001000 -> dwInitialSize // // EBX: 00040000 -> flOptions // // ESP: ???????? -> No Change // // EBP: ???????? -> Jmp Esp / Call Esp // // ESI: ???????? -> ApiAddresses["HeapCreate"] // // EDI: ???????? -> RopNop // //////////////////////////////////////////////////////////////// ErcResult>> HeapCreate = new ErcResult>>(info.ProcessCore); HeapCreate.ReturnValue = new List>(); Register32 regState32 = new Register32(); regState32 |= Register32.ESP; RegisterModifiers32 regModified32 = new RegisterModifiers32(); foreach (Register32 i in Enum.GetValues(typeof(Register32))) { SetRegisterModifier(regModified32.ESP, i, regModified32); SetRegisterModifier(i, regModified32.ESP, regModified32); } RegisterLists32 regLists32 = new RegisterLists32(); while (!CompleteRegisters32(regState32)) { #region Populate EDI if (!regState32.HasFlag(Register32.EDI)) { regLists32.ediList = null; regLists32.ediList = new List>(); for (int i = 0; i < usableX86Opcodes.popEdi.Count; i++) { if (!regState32.HasFlag(Register32.EDI)) { if (usableX86Opcodes.popEdi.ElementAt(i).Value.Length <= 14 && !usableX86Opcodes.popEdi.ElementAt(i).Value.Contains("invalid")) { regLists32.ediList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(BitConverter.GetBytes((long)usableX86Opcodes.popEdi.ElementAt(i).Key)), usableX86Opcodes.popEdi.ElementAt(i).Value)); regLists32.ediList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(BitConverter.GetBytes((long)RopNops[0])), "ROP NOP")); regState32 |= Register32.EDI; } } else { i = usableX86Opcodes.popEdi.Count; } } foreach (Register32 i in Enum.GetValues(typeof(Register32))) { if (!regState32.HasFlag(Register32.EDI)) { var popInstruction = GetPopInstruction(Register32.EDI, i, regModified32); if (popInstruction != null) { var movInstruction = GetMovInstruction(Register32.EDI, i); if (movInstruction != null) { regLists32.ediList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(popInstruction.Item1), popInstruction.Item2)); regLists32.ediList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(BitConverter.GetBytes((long)RopNops[0])), "ROP NOP")); regLists32.ediList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(movInstruction.Item1), movInstruction.Item2)); SetRegisterModifier(Register32.EDI, i, regModified32); regState32 &= ~i; regState32 |= Register32.EDI; } } } else { break; } } if (!regState32.HasFlag(Register32.EDI)) { regLists32.ediList = null; regLists32.ediList = new List>(); byte[] nullBytes = new byte[] { 0x00, 0x00, 0x00, 0x00 }; regLists32.ediList.Add(Tuple.Create(nullBytes, "Unable to find appropriate instruction. EDI must be allocated manually")); regState32 |= Register32.EDI; } } #endregion #region Populate ESI if (!regState32.HasFlag(Register32.ESI)) { regLists32.esiList = null; regLists32.esiList = new List>(); for (int i = 0; i < usableX86Opcodes.popEsi.Count; i++) { if (!regState32.HasFlag(Register32.ESI)) { if (usableX86Opcodes.popEsi.ElementAt(i).Value.Length <= 14 && !usableX86Opcodes.popEsi.ElementAt(i).Value.Contains("invalid")) { regLists32.esiList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(BitConverter.GetBytes((long)usableX86Opcodes.popEsi.ElementAt(i).Key)), usableX86Opcodes.popEsi.ElementAt(i).Value)); regLists32.esiList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(BitConverter.GetBytes((long)ApiAddresses["HeapCreate"])), "Pointer to HeapCreate.")); regState32 |= Register32.ESI; } } else { i = usableX86Opcodes.popEsi.Count; } } if (!regState32.HasFlag(Register32.ESI)) { foreach (Register32 i in Enum.GetValues(typeof(Register32))) { if (!regState32.HasFlag(Register32.ESI)) { var popInstruction = GetPopInstruction(Register32.ESI, i, regModified32); if (popInstruction != null) { var movInstruction = GetMovInstruction(Register32.ESI, i); if (movInstruction != null) { regLists32.esiList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(popInstruction.Item1), popInstruction.Item2)); regLists32.esiList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(BitConverter.GetBytes((long)ApiAddresses["HeapCreate"])), "Pointer to HeapCreate.")); regLists32.esiList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(movInstruction.Item1), movInstruction.Item2)); SetRegisterModifier(Register32.ESI, i, regModified32); regState32 &= ~i; regState32 |= Register32.ESI; } } } } if (!regState32.HasFlag(Register32.ESI)) { regLists32.esiList = null; regLists32.esiList = new List>(); byte[] nullBytes = new byte[] { 0x00, 0x00, 0x00, 0x00 }; regLists32.esiList.Add(Tuple.Create(nullBytes, "Unable to find appropriate instruction. ESI must be allocated manually")); regState32 |= Register32.ESI; } } } #endregion #region Populate EBP if (!regState32.HasFlag(Register32.EBP)) { regLists32.ebpList = null; regLists32.ebpList = new List>(); for (int i = 0; i < usableX86Opcodes.popEbp.Count; i++) { if (!regState32.HasFlag(Register32.EBP)) { if (usableX86Opcodes.popEbp.ElementAt(i).Value.Length <= 14 && !usableX86Opcodes.popEbp.ElementAt(i).Value.Contains("invalid")) { regLists32.ebpList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(BitConverter.GetBytes((long)usableX86Opcodes.popEbp.ElementAt(i).Key)), usableX86Opcodes.popEbp.ElementAt(i).Value)); if (usableX86Opcodes.jmpEsp.Count > 0) { regLists32.ebpList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(BitConverter.GetBytes((long)usableX86Opcodes.jmpEsp.ElementAt(0).Key)), usableX86Opcodes.jmpEsp.ElementAt(0).Value)); } else { regLists32.ebpList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(BitConverter.GetBytes((long)usableX86Opcodes.callEsp.ElementAt(0).Key)), usableX86Opcodes.callEsp.ElementAt(0).Value)); } regState32 |= Register32.EBP; } } else { i = usableX86Opcodes.popEbp.Count; } } if (!regState32.HasFlag(Register32.EBP)) { foreach (Register32 i in Enum.GetValues(typeof(Register32))) { if (!regState32.HasFlag(Register32.EBP)) { var popInstruction = GetPopInstruction(Register32.EBP, i, regModified32); if (popInstruction != null) { var movInstruction = GetMovInstruction(Register32.EBP, i); if (movInstruction != null) { regLists32.ebpList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(popInstruction.Item1), popInstruction.Item2)); if (usableX86Opcodes.jmpEsp.Count > 0) { regLists32.ebpList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(BitConverter.GetBytes((long)usableX86Opcodes.jmpEsp.ElementAt(0).Key)), usableX86Opcodes.jmpEsp.ElementAt(0).Value)); } else { regLists32.ebpList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(BitConverter.GetBytes((long)usableX86Opcodes.callEsp.ElementAt(0).Key)), usableX86Opcodes.callEsp.ElementAt(0).Value)); } regLists32.ebpList.Add(Tuple.Create(movInstruction.Item1, movInstruction.Item2)); SetRegisterModifier(Register32.EBP, i, regModified32); regState32 &= ~i; regState32 |= Register32.EBP; } } } } if (!regState32.HasFlag(Register32.EBP)) { regLists32.ebpList = null; regLists32.ebpList = new List>(); byte[] nullBytes = new byte[] { 0x00, 0x00, 0x00, 0x00 }; regLists32.ebpList.Add(Tuple.Create(nullBytes, "Unable to find appropriate instruction. EBP must be allocated manually")); regState32 |= Register32.EBP; } } } #endregion #region Populate EBX // Populate EBX if (!regState32.HasFlag(Register32.EBX)) { byte[] flOptions = new byte[] { 0x00, 0x04, 0x00, 0x00 }; regLists32.ebxList = null; regLists32.ebxList = new List>(); for (int i = 0; i < usableX86Opcodes.popEbx.Count; i++) { if (!regState32.HasFlag(Register32.EBX)) { if (usableX86Opcodes.popEbx.ElementAt(i).Value.Length <= 14 && !usableX86Opcodes.popEbx.ElementAt(i).Value.Contains("invalid")) { regLists32.ebxList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(BitConverter.GetBytes((long)usableX86Opcodes.popEbx.ElementAt(i).Key)), usableX86Opcodes.popEbx.ElementAt(i).Value)); regLists32.ebxList.Add(Tuple.Create(flOptions, "flOptions")); regState32 |= Register32.EBX; } } else { i = usableX86Opcodes.popEbx.Count; } } foreach (Register32 i in Enum.GetValues(typeof(Register32))) { if (!regState32.HasFlag(Register32.EBX)) { var popInstruction = GetPopInstruction(Register32.EBX, i, regModified32); if (popInstruction != null) { var movInstruction = GetMovInstruction(Register32.EBX, i); if (movInstruction != null) { regLists32.ebxList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(popInstruction.Item1), popInstruction.Item2)); regLists32.ebxList.Add(Tuple.Create(flOptions, "flOptions")); regLists32.ebxList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(movInstruction.Item1), movInstruction.Item2)); SetRegisterModifier(Register32.EBX, i, regModified32); regState32 &= ~i; regState32 |= Register32.EBX; } } } else { break; } } if (!regState32.HasFlag(Register32.EBX)) { regLists32.ebxList = null; regLists32.ebxList = new List>(); byte[] nullBytes = new byte[] { 0x00, 0x00, 0x00, 0x00 }; regLists32.ebxList.Add(Tuple.Create(nullBytes, "Unable to find appropriate instruction. EBX must be allocated manually")); regState32 |= Register32.EBX; } } #endregion #region Populate EDX if (!regState32.HasFlag(Register32.EDX)) { byte[] dwInitialSize = new byte[] { 0x00, 0x00, 0x10, 0x00 }; regLists32.edxList = null; regLists32.edxList = new List>(); for (int i = 0; i < usableX86Opcodes.popEdx.Count; i++) { if (!regState32.HasFlag(Register32.EDX)) { if (usableX86Opcodes.popEdx.ElementAt(i).Value.Length <= 14 && !usableX86Opcodes.popEdx.ElementAt(i).Value.Contains("invalid")) { regLists32.edxList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(BitConverter.GetBytes((long)usableX86Opcodes.popEdx.ElementAt(i).Key)), usableX86Opcodes.popEdx.ElementAt(i).Value)); regLists32.edxList.Add(Tuple.Create(dwInitialSize, "dwInitialSize")); regState32 |= Register32.EDX; } } else { i = usableX86Opcodes.popEdx.Count; } } foreach (Register32 i in Enum.GetValues(typeof(Register32))) { if (!regState32.HasFlag(Register32.EDX)) { var popInstruction = GetPopInstruction(Register32.EDX, i, regModified32); if (popInstruction != null) { var movInstruction = GetMovInstruction(Register32.EDX, i); if (movInstruction != null) { regLists32.edxList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(popInstruction.Item1), popInstruction.Item2)); regLists32.edxList.Add(Tuple.Create(dwInitialSize, "dwInitialSize")); regLists32.edxList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(movInstruction.Item1), movInstruction.Item2)); SetRegisterModifier(Register32.EDX, i, regModified32); regState32 &= ~i; regState32 |= Register32.EDX; } } } else { break; } } if (!regState32.HasFlag(Register32.EDX)) { regLists32.edxList = null; regLists32.edxList = new List>(); byte[] nullBytes = new byte[] { 0x00, 0x00, 0x00, 0x00 }; regLists32.edxList.Add(Tuple.Create(nullBytes, "Unable to find appropriate instruction. EDX must be allocated manually")); regState32 |= Register32.EDX; } } #endregion #region Populate ECX if (!regState32.HasFlag(Register32.ECX)) { byte[] dwMaximumSize = new byte[] { 0x00, 0x01, 0x00, 0x00 }; regLists32.ecxList = null; regLists32.ecxList = new List>(); for (int i = 0; i < usableX86Opcodes.popEcx.Count; i++) { if (!regState32.HasFlag(Register32.ECX)) { if (usableX86Opcodes.popEcx.ElementAt(i).Value.Length <= 14 && !usableX86Opcodes.popEcx.ElementAt(i).Value.Contains("invalid")) { regLists32.ecxList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(BitConverter.GetBytes((long)usableX86Opcodes.popEcx.ElementAt(i).Key)), usableX86Opcodes.popEcx.ElementAt(i).Value)); regLists32.ecxList.Add(Tuple.Create(dwMaximumSize, "dwMaximumSize")); regState32 |= Register32.ECX; } } else { i = usableX86Opcodes.popEcx.Count; } } foreach (Register32 i in Enum.GetValues(typeof(Register32))) { if (!regState32.HasFlag(Register32.ECX)) { var popInstruction = GetPopInstruction(Register32.ECX, i, regModified32); if (popInstruction != null) { var movInstruction = GetMovInstruction(Register32.ECX, i); if (movInstruction != null) { regLists32.ecxList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(popInstruction.Item1), popInstruction.Item2)); regLists32.ecxList.Add(Tuple.Create(dwMaximumSize, "dwMaximumSize")); regLists32.ecxList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(movInstruction.Item1), movInstruction.Item2)); SetRegisterModifier(Register32.ECX, i, regModified32); regState32 &= ~i; regState32 |= Register32.ECX; } } } else { break; } } if (!regState32.HasFlag(Register32.ECX)) { regLists32.ecxList = null; regLists32.ecxList = new List>(); byte[] nullBytes = new byte[] { 0x00, 0x00, 0x00, 0x00 }; regLists32.ecxList.Add(Tuple.Create(nullBytes, "Unable to find appropriate instruction. ECX must be allocated manually")); regState32 |= Register32.ECX; } } #endregion #region Populate EAX if (!regState32.HasFlag(Register32.EAX)) { byte[] nops = new byte[] { 0x90, 0x90, 0x90, 0x90 }; regLists32.eaxList = null; regLists32.eaxList = new List>(); for (int i = 0; i < usableX86Opcodes.popEax.Count; i++) { if (!regState32.HasFlag(Register32.EAX)) { if (usableX86Opcodes.popEax.ElementAt(i).Value.Length <= 14 && !usableX86Opcodes.popEax.ElementAt(i).Value.Contains("invalid")) { regLists32.eaxList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(BitConverter.GetBytes((long)usableX86Opcodes.popEax.ElementAt(i).Key)), usableX86Opcodes.popEax.ElementAt(i).Value)); regLists32.eaxList.Add(Tuple.Create(nops, "NOPS")); regState32 |= Register32.EAX; } } else { i = usableX86Opcodes.popEax.Count; } } foreach (Register32 i in Enum.GetValues(typeof(Register32))) { if (!regState32.HasFlag(Register32.EAX)) { var popInstruction = GetPopInstruction(Register32.EAX, i, regModified32); if (popInstruction != null) { var movInstruction = GetMovInstruction(Register32.EAX, i); if (movInstruction != null) { regLists32.eaxList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(popInstruction.Item1), popInstruction.Item2)); regLists32.eaxList.Add(Tuple.Create(nops, "NOPS")); regLists32.eaxList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(movInstruction.Item1), movInstruction.Item2)); SetRegisterModifier(Register32.EAX, i, regModified32); regState32 &= ~i; regState32 |= Register32.EAX; } } } else { break; } } if (!regState32.HasFlag(Register32.EAX)) { regLists32.eaxList = null; regLists32.eaxList = new List>(); byte[] nullBytes = new byte[] { 0x00, 0x00, 0x00, 0x00 }; regLists32.eaxList.Add(Tuple.Create(nullBytes, "Unable to find appropriate instruction. EAX must be allocated manually")); regState32 |= Register32.EAX; } } #endregion } HeapCreate.ReturnValue = BuildRopChain(regLists32, regModified32); return HeapCreate; } #endregion #region GenerateVirtualProtectChain32 private ErcResult>> GenerateVirtualProtectChain32(ProcessInfo info) { //////////////////////////////////////////////////////////////// // VirtualProtect Template: // // EAX: 90909090 -> Nop sled // // ECX: ???????? -> lpflOldProtect // // EDX: 00000040 -> flNewProtect // // EBX: ???????? -> Int size (area to be set as executable) // // ESP: ???????? -> No Change // // EBP: ???????? -> Jmp Esp / Call Esp // // ESI: ???????? -> ApiAddresses["VirtualProtect"] // // EDI: ???????? -> RopNop // // // // + place ptr to "jmp esp" on stack, below PUSHAD // //////////////////////////////////////////////////////////////// ErcResult>> VirtualAlloc = new ErcResult>>(info.ProcessCore); VirtualAlloc.ReturnValue = new List>(); Register32 regState32 = new Register32(); regState32 |= Register32.ESP; RegisterModifiers32 regModified32 = new RegisterModifiers32(); foreach (Register32 i in Enum.GetValues(typeof(Register32))) { SetRegisterModifier(regModified32.ESP, i, regModified32); SetRegisterModifier(i, regModified32.ESP, regModified32); } RegisterLists32 regLists32 = new RegisterLists32(); while (!CompleteRegisters32(regState32)) { #region Populate EDI if (!regState32.HasFlag(Register32.EDI)) { regLists32.ediList = null; regLists32.ediList = new List>(); for (int i = 0; i < usableX86Opcodes.popEdi.Count; i++) { if (!regState32.HasFlag(Register32.EDI)) { if (usableX86Opcodes.popEdi.ElementAt(i).Value.Length <= 14 && !usableX86Opcodes.popEdi.ElementAt(i).Value.Contains("invalid")) { regLists32.ediList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(BitConverter.GetBytes((long)usableX86Opcodes.popEdi.ElementAt(i).Key)), usableX86Opcodes.popEdi.ElementAt(i).Value)); regLists32.ediList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(BitConverter.GetBytes((long)RopNops[0])), "ROP NOP")); regState32 |= Register32.EDI; } } else { i = usableX86Opcodes.popEdi.Count; } } foreach (Register32 i in Enum.GetValues(typeof(Register32))) { if (!regState32.HasFlag(Register32.EDI)) { var popInstruction = GetPopInstruction(Register32.EDI, i, regModified32); if (popInstruction != null) { var movInstruction = GetMovInstruction(Register32.EDI, i); if (movInstruction != null) { regLists32.ediList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(popInstruction.Item1), popInstruction.Item2)); regLists32.ediList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(BitConverter.GetBytes((long)RopNops[0])), "ROP NOP")); regLists32.ediList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(movInstruction.Item1), movInstruction.Item2)); SetRegisterModifier(Register32.EDI, i, regModified32); regState32 &= ~i; regState32 |= Register32.EDI; } } } else { break; } } if (!regState32.HasFlag(Register32.EDI)) { regLists32.ediList = null; regLists32.ediList = new List>(); byte[] nullBytes = new byte[] { 0x00, 0x00, 0x00, 0x00 }; regLists32.ediList.Add(Tuple.Create(nullBytes, "Unable to find appropriate instruction. EDI must be allocated manually")); regState32 |= Register32.EDI; } } #endregion #region Populate ESI if (!regState32.HasFlag(Register32.ESI)) { regLists32.esiList = null; regLists32.esiList = new List>(); for (int i = 0; i < usableX86Opcodes.popEsi.Count; i++) { if (!regState32.HasFlag(Register32.ESI)) { if (usableX86Opcodes.popEsi.ElementAt(i).Value.Length <= 14 && !usableX86Opcodes.popEsi.ElementAt(i).Value.Contains("invalid")) { regLists32.esiList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(BitConverter.GetBytes((long)usableX86Opcodes.popEsi.ElementAt(i).Key)), usableX86Opcodes.popEsi.ElementAt(i).Value)); regLists32.esiList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(BitConverter.GetBytes((long)ApiAddresses["VirtualAlloc"])), "Pointer to VirtualAlloc.")); regState32 |= Register32.ESI; } } else { i = usableX86Opcodes.popEsi.Count; } } if (!regState32.HasFlag(Register32.ESI)) { foreach (Register32 i in Enum.GetValues(typeof(Register32))) { if (!regState32.HasFlag(Register32.ESI)) { var popInstruction = GetPopInstruction(Register32.ESI, i, regModified32); if (popInstruction != null) { var movInstruction = GetMovInstruction(Register32.ESI, i); if (movInstruction != null) { regLists32.esiList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(popInstruction.Item1), popInstruction.Item2)); regLists32.esiList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(BitConverter.GetBytes((long)ApiAddresses["VirtualAlloc"])), "Pointer to VirtualAlloc.")); regLists32.esiList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(movInstruction.Item1), movInstruction.Item2)); SetRegisterModifier(Register32.ESI, i, regModified32); regState32 &= ~i; regState32 |= Register32.ESI; } } } } if (!regState32.HasFlag(Register32.ESI)) { regLists32.esiList = null; regLists32.esiList = new List>(); byte[] nullBytes = new byte[] { 0x00, 0x00, 0x00, 0x00 }; regLists32.esiList.Add(Tuple.Create(nullBytes, "Unable to find appropriate instruction. ESI must be allocated manually")); regState32 |= Register32.ESI; } } } #endregion #region Populate EBP if (!regState32.HasFlag(Register32.EBP)) { regLists32.ebpList = null; regLists32.ebpList = new List>(); for (int i = 0; i < usableX86Opcodes.popEbp.Count; i++) { if (!regState32.HasFlag(Register32.EBP)) { if (usableX86Opcodes.popEbp.ElementAt(i).Value.Length <= 14 && !usableX86Opcodes.popEbp.ElementAt(i).Value.Contains("invalid")) { regLists32.ebpList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(BitConverter.GetBytes((long)usableX86Opcodes.popEbp.ElementAt(i).Key)), usableX86Opcodes.popEbp.ElementAt(i).Value)); if (usableX86Opcodes.jmpEsp.Count > 0) { regLists32.ebpList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(BitConverter.GetBytes((long)usableX86Opcodes.jmpEsp.ElementAt(0).Key)), usableX86Opcodes.jmpEsp.ElementAt(0).Value)); } else { regLists32.ebpList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(BitConverter.GetBytes((long)usableX86Opcodes.callEsp.ElementAt(0).Key)), usableX86Opcodes.callEsp.ElementAt(0).Value)); } regState32 |= Register32.EBP; } } else { i = usableX86Opcodes.popEbp.Count; } } if (!regState32.HasFlag(Register32.EBP)) { foreach (Register32 i in Enum.GetValues(typeof(Register32))) { if (!regState32.HasFlag(Register32.EBP)) { var popInstruction = GetPopInstruction(Register32.EBP, i, regModified32); if (popInstruction != null) { var movInstruction = GetMovInstruction(Register32.EBP, i); if (movInstruction != null) { regLists32.ebpList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(popInstruction.Item1), popInstruction.Item2)); if (usableX86Opcodes.jmpEsp.Count > 0) { regLists32.ebpList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(BitConverter.GetBytes((long)usableX86Opcodes.jmpEsp.ElementAt(0).Key)), usableX86Opcodes.jmpEsp.ElementAt(0).Value)); } else { regLists32.ebpList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(BitConverter.GetBytes((long)usableX86Opcodes.callEsp.ElementAt(0).Key)), usableX86Opcodes.callEsp.ElementAt(0).Value)); } regLists32.ebpList.Add(Tuple.Create(movInstruction.Item1, movInstruction.Item2)); SetRegisterModifier(Register32.EBP, i, regModified32); regState32 &= ~i; regState32 |= Register32.EBP; } } } } if (!regState32.HasFlag(Register32.EBP)) { regLists32.ebpList = null; regLists32.ebpList = new List>(); byte[] nullBytes = new byte[] { 0x00, 0x00, 0x00, 0x00 }; regLists32.ebpList.Add(Tuple.Create(nullBytes, "Unable to find appropriate instruction. EBP must be allocated manually")); regState32 |= Register32.EBP; } } } #endregion #region Populate EBX // Populate EBX if (!regState32.HasFlag(Register32.EBX)) { regLists32.ebxList = null; regLists32.ebxList = new List>(); var xorEbx = GetXorInstruction(Register32.EBX); if (xorEbx != null) { regLists32.ebxList.Add(Tuple.Create(xorEbx.Item1, xorEbx.Item2)); if (usableX86Opcodes.incEbx.Count > 0) { if (usableX86Opcodes.incEbx.ElementAt(0).Value.Length <= 14) { regLists32.ebxList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(BitConverter.GetBytes((long)usableX86Opcodes.incEbx.ElementAt(0).Key)), usableX86Opcodes.incEbx.ElementAt(0).Value)); regState32 |= Register32.EBX; } } } if (!regState32.HasFlag(Register32.EBX)) { var zeroEbx = ZeroRegister(Register32.EBX, regModified32); if (zeroEbx != null && usableX86Opcodes.incEbx.Count > 0 && usableX86Opcodes.incEbx.ElementAt(0).Value.Length <= 14) { for (int i = 0; i < zeroEbx.Count; i++) { regLists32.ebxList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(zeroEbx[i].Item1), zeroEbx[i].Item2)); } regLists32.ebxList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier( BitConverter.GetBytes((long)usableX86Opcodes.incEbx.ElementAt(0).Key)), usableX86Opcodes.incEbx.ElementAt(0).Value)); SetRegisterModifier(Register32.EBX, zeroEbx[0].Item3, regModified32); regState32 &= ~zeroEbx[0].Item3; regState32 |= Register32.EBX; } } if (!regState32.HasFlag(Register32.EBX)) { foreach (Register32 i in Enum.GetValues(typeof(Register32))) { var popInstruction = GetPopInstruction(Register32.EBP, i, regModified32); if (popInstruction != null) { for (int j = 0; j < x86Opcodes.add.Count; j++) { if (!regState32.HasFlag(Register32.EBX)) { var strings = x86Opcodes.add.ElementAt(j).Value.Split(','); if (strings[0].Contains(" ebx") && strings[1].Contains(i.ToString().ToLower())) { regLists32.ebxList.Add(Tuple.Create(popInstruction.Item1, popInstruction.Item2)); byte[] bytes = new byte[] { 0xFF, 0xFF, 0xFF, 0xFF };//......................................replace this with a more long term solution. Dynamically allocate size based on the size category in regLists32.ebxList.Add(Tuple.Create(bytes, "To be popped into " + i.ToString())); regLists32.ebxList.Add(Tuple.Create(BitConverter.GetBytes((long)x86Opcodes.add.ElementAt(j).Key), x86Opcodes.add.ElementAt(j).Value)); regLists32.ebxList.Add(Tuple.Create(popInstruction.Item1, popInstruction.Item2)); bytes = new byte[] { 0x01, 0x01, 0x10, 0x01 };//......................................replace this with a more long term solution. Dynamically allocate size based on the size category in regLists32.ebxList.Add(Tuple.Create(bytes, "To be popped into " + i.ToString())); regLists32.ebxList.Add(Tuple.Create(BitConverter.GetBytes((long)x86Opcodes.add.ElementAt(j).Key), x86Opcodes.add.ElementAt(j).Value)); SetRegisterModifier(Register32.EBX, i, regModified32); regState32 &= ~i; regState32 |= Register32.EBX; } } } } } } } if (!regState32.HasFlag(Register32.EBX)) { regLists32.ebxList = null; regLists32.ebxList = new List>(); byte[] nullBytes = new byte[] { 0x00, 0x00, 0x00, 0x00 }; regLists32.ebxList.Add(Tuple.Create(nullBytes, "Unable to find appropriate instruction. EBX must be allocated manually")); regState32 |= Register32.EBX; } #endregion #region Populate EDX //Populate EDX if (!regState32.HasFlag(Register32.EDX)) { regLists32.edxList = null; regLists32.edxList = new List>(); var xorEDX = GetXorInstruction(Register32.EDX); if (xorEDX != null) { foreach (Register32 i in Enum.GetValues(typeof(Register32))) { if (!regState32.HasFlag(Register32.EDX)) { var popInstruction = GetPopInstruction(Register32.EDX, i, regModified32); if (popInstruction != null) { var addInstruction = GetAddInstruction(Register32.EDX, i); if (addInstruction != null) { byte[] add1 = new byte[] { 0xFF, 0xFF, 0xFF, 0xFF }; byte[] add2 = new byte[] { 0x01, 0x11, 0x01, 0x01 }; regLists32.edxList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(xorEDX.Item1), xorEDX.Item2)); regLists32.edxList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(popInstruction.Item1), popInstruction.Item2)); regLists32.edxList.Add(Tuple.Create(add1, "To be placed into " + addInstruction.Item3.ToString())); regLists32.edxList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(addInstruction.Item1), addInstruction.Item2)); regLists32.edxList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(popInstruction.Item1), popInstruction.Item2)); regLists32.edxList.Add(Tuple.Create(add2, "To be placed into " + addInstruction.Item3.ToString() + " combined = 0x00000040")); regLists32.edxList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(addInstruction.Item1), addInstruction.Item2)); SetRegisterModifier(Register32.EDX, i, regModified32); regState32 &= ~i; regState32 |= Register32.EDX; } } } } } if (!regState32.HasFlag(Register32.EDX)) { foreach (Register32 i in Enum.GetValues(typeof(Register32))) { var popInstruction = GetPopInstruction(Register32.EDX, i, regModified32); if (popInstruction != null) { foreach (Register32 j in Enum.GetValues(typeof(Register32))) { if (!regState32.HasFlag(Register32.EDX) && i != j) { var popInstruction2 = GetPopInstruction(Register32.EDX, j, regModified32); if (popInstruction2 != null) { var addInstruction = GetAddInstruction(i, j); if (addInstruction != null) { var movInstruction = GetMovInstruction(Register32.EDX, i); if (movInstruction != null) { byte[] add1 = new byte[] { 0xFF, 0xFF, 0xFF, 0xFF }; byte[] add2 = new byte[] { 0x41, 0x01, 0x01, 0x01 }; regLists32.edxList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(popInstruction.Item1), popInstruction.Item2)); regLists32.edxList.Add(Tuple.Create(add1, "To be placed into " + popInstruction.Item3.ToString())); regLists32.edxList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(popInstruction2.Item1), popInstruction2.Item2)); regLists32.edxList.Add(Tuple.Create(add2, "To be placed into " + addInstruction.Item3.ToString() + " combined = 0x00001000")); regLists32.edxList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(addInstruction.Item1), addInstruction.Item2)); regLists32.edxList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(movInstruction.Item1), movInstruction.Item2)); SetRegisterModifier(Register32.EDX, i, regModified32); SetRegisterModifier(Register32.EDX, j, regModified32); regState32 &= ~i; regState32 &= ~j; regState32 |= Register32.EDX; } } } } } } } } if (!regState32.HasFlag(Register32.EDX)) { regLists32.edxList = null; regLists32.edxList = new List>(); byte[] nullBytes = new byte[] { 0x00, 0x00, 0x00, 0x00 }; regLists32.edxList.Add(Tuple.Create(nullBytes, "Unable to find appropriate instruction. EDX must be allocated manually")); regState32 |= Register32.EDX; } } #endregion #region Populate ECX //Populate ECX if (!regState32.HasFlag(Register32.ECX)) { regLists32.ecxList = null; regLists32.ecxList = new List>(); var xorECX = GetXorInstruction(Register32.ECX); if (xorECX != null) { if (!regState32.HasFlag(Register32.ECX)) { var movInstruction = GetMovInstruction(Register32.ECX, Register32.ESP); if (movInstruction != null && !movInstruction.Item2.Contains("invalid")) { regLists32.ecxList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(movInstruction.Item1), movInstruction.Item2)); regState32 |= Register32.ECX; } else if (usableX86Opcodes.pushEsp.Count > 0 && usableX86Opcodes.popEcx.Count > 0) { bool pushEsp = false; bool popEcx = false; for(int i = 0; i < usableX86Opcodes.pushEsp.Count; i++) { if (usableX86Opcodes.pushEsp.ElementAt(i).Value.Length <= 14 && !usableX86Opcodes.pushEsp.ElementAt(i).Value.Contains("invalid")) { regLists32.ecxList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(movInstruction.Item1), movInstruction.Item2)); pushEsp = true; i = usableX86Opcodes.pushEsp.Count + 1; } } for (int i = 0; i < usableX86Opcodes.popEcx.Count; i++) { if (usableX86Opcodes.popEcx.ElementAt(i).Value.Length <= 14 && !usableX86Opcodes.popEcx.ElementAt(i).Value.Contains("invalid")) { regLists32.ecxList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(movInstruction.Item1), movInstruction.Item2)); pushEsp = true; i = usableX86Opcodes.popEcx.Count + 1; } } if (pushEsp == true && popEcx == true) { regState32 |= Register32.ECX; } else if(pushEsp == true && popEcx == false) { byte[] nullBytes = new byte[] { 0x00, 0x00, 0x00, 0x00 }; regLists32.ecxList.Add(Tuple.Create(nullBytes, "Unable to find POP ECX instruction. Must be filled manually")); } else if(pushEsp == false && popEcx == true) { byte[] nullBytes = new byte[] { 0x00, 0x00, 0x00, 0x00 }; regLists32.ecxList.Add(Tuple.Create(nullBytes, "Unable to find PUSH ESP instruction. Must be filled manually")); } } } } if (!regState32.HasFlag(Register32.ECX)) { regLists32.ecxList = null; regLists32.ecxList = new List>(); byte[] nullBytes = new byte[] { 0x00, 0x00, 0x00, 0x00 }; regLists32.ecxList.Add(Tuple.Create(nullBytes, "Unable to find appropriate instruction. ECX must be allocated manually")); regState32 |= Register32.ECX; } } #endregion #region Populate EAX if (!regState32.HasFlag(Register32.EAX)) { byte[] nops = new byte[] { 0x90, 0x90, 0x90, 0x90 }; regLists32.eaxList = null; regLists32.eaxList = new List>(); for (int i = 0; i < usableX86Opcodes.popEax.Count; i++) { if (!regState32.HasFlag(Register32.EAX)) { if (usableX86Opcodes.popEax.ElementAt(i).Value.Length <= 14 && !usableX86Opcodes.popEax.ElementAt(i).Value.Contains("invalid")) { regLists32.eaxList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(BitConverter.GetBytes((long)usableX86Opcodes.popEax.ElementAt(i).Key)), usableX86Opcodes.popEax.ElementAt(i).Value)); regLists32.eaxList.Add(Tuple.Create(nops, "NOPS")); regState32 |= Register32.EAX; } } else { i = usableX86Opcodes.popEax.Count; } } foreach (Register32 i in Enum.GetValues(typeof(Register32))) { if (!regState32.HasFlag(Register32.EAX)) { var popInstruction = GetPopInstruction(Register32.EAX, i, regModified32); if (popInstruction != null) { var movInstruction = GetMovInstruction(Register32.EAX, i); if (movInstruction != null) { regLists32.eaxList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(popInstruction.Item1), popInstruction.Item2)); regLists32.eaxList.Add(Tuple.Create(nops, "NOPS")); regLists32.eaxList.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(movInstruction.Item1), movInstruction.Item2)); SetRegisterModifier(Register32.EAX, i, regModified32); regState32 &= ~i; regState32 |= Register32.EAX; } } } else { break; } } if (!regState32.HasFlag(Register32.EAX)) { regLists32.eaxList = null; regLists32.eaxList = new List>(); byte[] nullBytes = new byte[] { 0x00, 0x00, 0x00, 0x00 }; regLists32.eaxList.Add(Tuple.Create(nullBytes, "Unable to find appropriate instruction. EAX must be allocated manually")); regState32 |= Register32.EAX; } } #endregion } VirtualAlloc.ReturnValue = BuildRopChain(regLists32, regModified32, true); return VirtualAlloc; } #endregion #region GenerateWriteProcessMemoryChain32 private ErcResult>> GenerateWriteProcessMemoryChain32(ProcessInfo info, byte[] startAddress) { return null; } #endregion #region BuildRopChain private List> BuildRopChain(RegisterLists32 regLists32, RegisterModifiers32 regModified32, bool addJmpEsp = false) { List> ret = new List>(); List order = new List(); order.Add((ushort)regModified32.EAX); order.Add((ushort)regModified32.EBX); order.Add((ushort)regModified32.ECX); order.Add((ushort)regModified32.EDX); order.Add((ushort)regModified32.EBP); order.Add((ushort)regModified32.ESP); order.Add((ushort)regModified32.ESI); order.Add((ushort)regModified32.EDI); order = order.OrderByDescending(x => x).ToList(); order = order.Distinct().ToList(); for (int i = 0; i < order.Count; i++) { if((ushort)regModified32.EAX == order[i]) { for(int j = 0; j < regLists32.eaxList.Count; j++) { ret.Add(regLists32.eaxList[j]); } } if ((ushort)regModified32.EBX == order[i]) { for (int j = 0; j < regLists32.ebxList.Count; j++) { ret.Add(regLists32.ebxList[j]); } } if ((ushort)regModified32.ECX == order[i]) { for (int j = 0; j < regLists32.ecxList.Count; j++) { ret.Add(regLists32.ecxList[j]); } } if ((ushort)regModified32.EDX == order[i]) { for (int j = 0; j < regLists32.edxList.Count; j++) { ret.Add(regLists32.edxList[j]); } } if ((ushort)regModified32.EBP == order[i]) { for (int j = 0; j < regLists32.ebpList.Count; j++) { ret.Add(regLists32.ebpList[j]); } } if ((ushort)regModified32.ESP == order[i]) { for (int j = 0; j < regLists32.espList.Count; j++) { ret.Add(regLists32.espList[j]); } } if ((ushort)regModified32.ESI == order[i]) { for (int j = 0; j < regLists32.esiList.Count; j++) { ret.Add(regLists32.esiList[j]); } } if ((ushort)regModified32.EDI == order[i]) { for (int j = 0; j < regLists32.ediList.Count; j++) { ret.Add(regLists32.ediList[j]); } } } if (usableX86Opcodes.pushad.Count > 0 && usableX86Opcodes.pushad.ElementAt(0).Value.Length <= 15) ret.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(BitConverter.GetBytes((long)usableX86Opcodes.pushad.ElementAt(0).Key)), usableX86Opcodes.pushad.ElementAt(0).Value)); if(addJmpEsp == true) { ret.Add(Tuple.Create(ErcCore.X64toX32PointerModifier(BitConverter.GetBytes((long)usableX86Opcodes.jmpEsp.ElementAt(0).Key)), usableX86Opcodes.jmpEsp.ElementAt(0).Value)); } return ret; } #endregion #region CalculateAddInstructions32 (Needs Work) private byte[] CalculateAddInstructions32(int size) { byte[] sizeBytes = BitConverter.GetBytes(size); byte[] modifiedBytes = new byte[4]; Array.Copy(sizeBytes, 0, modifiedBytes, modifiedBytes.Length - sizeBytes.Length, sizeBytes.Length); for(int i = 0; i < modifiedBytes.Length; i++) { modifiedBytes[i] += 0x01; } return modifiedBytes; } #endregion #region ZeroRegister /// /// Checks for a combination of instructions that can be used to zero out a register, this can be a xor instruction on itself or a xor instruction elsewhere /// followed by a move to the selected register. This function should be extended with further methods for zeroing a register at a later date. /// /// The Register32 value for the register to be zeroed. /// The RegisterModifiers32 object. /// A dictionary(byte[], string) containing pointers to the instructions and the associated mnemonics private List> ZeroRegister(Register32 modifyingReg, RegisterModifiers32 regModified32) { List> instructions = new List>(); var xor = GetXorInstruction(modifyingReg); if (xor != null) { instructions.Add(xor); return instructions; } for (int i = 0; i < usableX86Opcodes.mov.Count; i++) { string[] gadgetElements = usableX86Opcodes.mov.ElementAt(i).Value.Split(','); if (gadgetElements[0].Contains(modifyingReg.ToString().ToLower())) { var reg = registerIdentifier32(gadgetElements[1]); if (reg != Register32.NONE && !GetRegisterModified(modifyingReg, reg, regModified32)) { var xorReg = GetXorInstruction(reg); if (xorReg != null && !GetRegisterModified(modifyingReg, reg, regModified32)) { instructions.Add(xorReg); instructions.Add(Tuple.Create(BitConverter.GetBytes((long)usableX86Opcodes.mov.ElementAt(i).Key), usableX86Opcodes.mov.ElementAt(i).Value, reg)); return instructions; } } } } return null; } #endregion #region SetRegisterModifier 32 bit /// /// Sets the flag of a Register32 enum in a RegisterModifiers32 class. This flag is used to identify whether setting the value of one /// register involved editing another register. For example if setting EAX involved modifying EBX then RegisterModifiers32.EAX will have the EBX flag set. Any /// register should not be able to modify the value of any other register twice. /// /// The purpose of this is to stop an infitinte loop where each register modifies the other in order to achieve the correct value. /// /// The Registers32 which is being modified /// The Registers32 which is doing the modification /// The RegisterModifiers32 object. private void SetRegisterModifier(Register32 modifyingReg, Register32 modifiedReg, RegisterModifiers32 regModified32) { switch (modifyingReg) { case Register32.EAX: regModified32.EAX |= modifiedReg; return; case Register32.EBX: regModified32.EBX |= modifiedReg; return; case Register32.ECX: regModified32.ECX |= modifiedReg; return; case Register32.EDX: regModified32.EDX |= modifiedReg; return; case Register32.EBP: regModified32.EBP |= modifiedReg; return; case Register32.ESP: regModified32.ESP |= modifiedReg; return; case Register32.ESI: regModified32.ESI |= modifiedReg; return; case Register32.EDI: regModified32.EDI |= modifiedReg; return; } } #endregion #region GetRegisterModifier 32 bit /// /// Returns a boolean indicating whether one register has modified the value of another register attempting to set the correct value. /// /// The Registers32 which is being modified /// The Registers32 which is doing the modification /// The RegisterModifiers32 object. /// A bool, true = register was modified by this register false = register was not modified by this register private bool GetRegisterModified(Register32 modifyingReg, Register32 modifiedReg, RegisterModifiers32 regModified32) { Register32 thisReg; bool modified = false; switch (modifyingReg) { case Register32.EAX: thisReg = regModified32.EAX; break; case Register32.EBX: thisReg = regModified32.EBX; break; case Register32.ECX: thisReg = regModified32.ECX; break; case Register32.EDX: thisReg = regModified32.EDX; break; case Register32.EBP: thisReg = regModified32.EBP; break; case Register32.ESP: thisReg = regModified32.ESP; break; case Register32.ESI: thisReg = regModified32.ESI; break; case Register32.EDI: thisReg = regModified32.EDI; break; default: return true; } if (thisReg.HasFlag(modifiedReg)) { modified = true; } return modified; } #endregion #region GetPopInstruction 32 bit private Tuple GetPopInstruction(Register32 destReg, Register32 srcReg, RegisterModifiers32 regModified32) { switch(srcReg){ case Register32.EAX: for (int i = 0; i < usableX86Opcodes.popEax.Count; i++) { if (usableX86Opcodes.popEax.ElementAt(i).Value.Length == 14 && !GetRegisterModified(destReg, Register32.EAX, regModified32)) { return Tuple.Create(BitConverter.GetBytes((long)usableX86Opcodes.popEax.ElementAt(i).Key), usableX86Opcodes.popEax.ElementAt(i).Value, Register32.EAX); } } break; case Register32.EBX: for (int i = 0; i < usableX86Opcodes.popEbx.Count; i++) { if (usableX86Opcodes.popEbx.ElementAt(i).Value.Length == 14 && !GetRegisterModified(destReg, Register32.EBX, regModified32)) { return Tuple.Create(BitConverter.GetBytes((long)usableX86Opcodes.popEbx.ElementAt(i).Key), usableX86Opcodes.popEbx.ElementAt(i).Value, Register32.EBX); } } break; case Register32.ECX: for (int i = 0; i < usableX86Opcodes.popEcx.Count; i++) { if (usableX86Opcodes.popEcx.ElementAt(i).Value.Length == 14 && !GetRegisterModified(destReg, Register32.ECX, regModified32)) { return Tuple.Create(BitConverter.GetBytes((long)usableX86Opcodes.popEcx.ElementAt(i).Key), usableX86Opcodes.popEcx.ElementAt(i).Value, Register32.ECX); } } break; case Register32.EDX: for (int i = 0; i < usableX86Opcodes.popEdx.Count; i++) { if (usableX86Opcodes.popEdx.ElementAt(i).Value.Length == 14 && !GetRegisterModified(destReg, Register32.EDX, regModified32)) { return Tuple.Create(BitConverter.GetBytes((long)usableX86Opcodes.popEdx.ElementAt(i).Key), usableX86Opcodes.popEdx.ElementAt(i).Value, Register32.EDX); } } break; case Register32.EBP: for (int i = 0; i < usableX86Opcodes.popEbp.Count; i++) { if (usableX86Opcodes.popEbp.ElementAt(i).Value.Length == 14 && !GetRegisterModified(destReg, Register32.EBP, regModified32)) { return Tuple.Create(BitConverter.GetBytes((long)usableX86Opcodes.popEbp.ElementAt(i).Key), usableX86Opcodes.popEbp.ElementAt(i).Value, Register32.EBP); } } break; case Register32.ESP: for (int i = 0; i < usableX86Opcodes.popEsp.Count; i++) { if (usableX86Opcodes.popEsp.ElementAt(i).Value.Length == 14 && !GetRegisterModified(destReg, Register32.ESP, regModified32)) { return Tuple.Create(BitConverter.GetBytes((long)usableX86Opcodes.popEsp.ElementAt(i).Key), usableX86Opcodes.popEsp.ElementAt(i).Value, Register32.ESP); } } break; case Register32.ESI: for (int i = 0; i < usableX86Opcodes.popEsi.Count; i++) { if (usableX86Opcodes.popEsi.ElementAt(i).Value.Length == 14 && !GetRegisterModified(destReg, Register32.ESI, regModified32)) { return Tuple.Create(BitConverter.GetBytes((long)usableX86Opcodes.popEsi.ElementAt(i).Key), usableX86Opcodes.popEsi.ElementAt(i).Value, Register32.ESI); } } break; case Register32.EDI: for (int i = 0; i < usableX86Opcodes.popEdi.Count; i++) { if (usableX86Opcodes.popEdi.ElementAt(i).Value.Length == 14 && !GetRegisterModified(destReg, Register32.EDI, regModified32)) { return Tuple.Create(BitConverter.GetBytes((long)usableX86Opcodes.popEdi.ElementAt(i).Key), usableX86Opcodes.popEdi.ElementAt(i).Value, Register32.EDI); } } break; default: return null; } return null; } #endregion #region getXorInstruction 32 bit private Tuple GetXorInstruction(Register32 reg) { switch (reg) { case Register32.EAX: if (usableX86Opcodes.xorEax.Count > 0 && usableX86Opcodes.xorEax.ElementAt(0).Value.Length <= 19) { byte[] gadget1 = BitConverter.GetBytes((long)usableX86Opcodes.xorEax.ElementAt(0).Key); return Tuple.Create(gadget1, usableX86Opcodes.xorEax.ElementAt(0).Value, Register32.EAX); } break; case Register32.EBX: if (usableX86Opcodes.xorEbx.Count > 0 && usableX86Opcodes.xorEbx.ElementAt(0).Value.Length <= 19) { byte[] gadget1 = BitConverter.GetBytes((long)usableX86Opcodes.xorEbx.ElementAt(0).Key); return Tuple.Create(gadget1, usableX86Opcodes.xorEbx.ElementAt(0).Value, Register32.EBX); } break; case Register32.ECX: if (usableX86Opcodes.xorEcx.Count > 0 && usableX86Opcodes.xorEcx.ElementAt(0).Value.Length <= 19) { byte[] gadget1 = BitConverter.GetBytes((long)usableX86Opcodes.xorEcx.ElementAt(0).Key); return Tuple.Create(gadget1, usableX86Opcodes.xorEcx.ElementAt(0).Value, Register32.ECX); } break; case Register32.EDX: if (usableX86Opcodes.xorEdx.Count > 0 && usableX86Opcodes.xorEdx.ElementAt(0).Value.Length <= 19) { byte[] gadget1 = BitConverter.GetBytes((long)usableX86Opcodes.xorEdx.ElementAt(0).Key); return Tuple.Create(gadget1, usableX86Opcodes.xorEdx.ElementAt(0).Value, Register32.EDX); } break; case Register32.ESI: if (usableX86Opcodes.xorEsi.Count > 0 && usableX86Opcodes.xorEsi.ElementAt(0).Value.Length <= 19) { byte[] gadget1 = BitConverter.GetBytes((long)usableX86Opcodes.xorEsi.ElementAt(0).Key); return Tuple.Create(gadget1, usableX86Opcodes.xorEsi.ElementAt(0).Value, Register32.ESI); } break; case Register32.EDI: if (usableX86Opcodes.xorEdi.Count > 0 && usableX86Opcodes.xorEdi.ElementAt(0).Value.Length <= 19) { byte[] gadget1 = BitConverter.GetBytes((long)usableX86Opcodes.xorEdi.ElementAt(0).Key); return Tuple.Create(gadget1, usableX86Opcodes.xorEdi.ElementAt(0).Value, Register32.EDI); } break; default: break; } return null; } #endregion #region GetMovInstruction 32 bit /// /// Finds a mov instruction going from the src register to the destination register /// /// The destination register /// The source register /// Returns a tuple of byte[], string, Register32 containing a pointer to the instruction and the associated mnemonics private Tuple GetMovInstruction(Register32 destReg, Register32 srcReg) { for (int i = 0; i < usableX86Opcodes.mov.Count; i++) { string[] gadgetElements = usableX86Opcodes.mov.ElementAt(i).Value.Split(','); if (gadgetElements[0].Contains(destReg.ToString().ToLower())) { var reg = registerIdentifier32(gadgetElements[1]); if (reg == srcReg) { return Tuple.Create(BitConverter.GetBytes((long)usableX86Opcodes.mov.ElementAt(i).Key), usableX86Opcodes.mov.ElementAt(i).Value, reg); } } } return null; } #endregion #region GetAddInstruction /// /// Finds a add instruction going from the src register to the destination register /// /// The destination register /// The source register /// Returns a tuple of byte[], string, Register32 containing a pointer to the instruction and the associated mnemonics private Tuple GetAddInstruction(Register32 destReg, Register32 srcReg) { for (int i = 0; i < usableX86Opcodes.add.Count; i++) { string[] gadgetElements = usableX86Opcodes.add.ElementAt(i).Value.Split(','); if(gadgetElements[0].Contains(destReg.ToString().ToLower())) { var reg = registerIdentifier32(gadgetElements[1]); if (reg == srcReg) { return Tuple.Create(BitConverter.GetBytes((long)usableX86Opcodes.add.ElementAt(i).Key), usableX86Opcodes.add.ElementAt(i).Value, reg); } } } return null; } #endregion #region registerIdentifier32 private Register32 registerIdentifier32(string reg) { switch (reg) { case " eax": return Register32.EAX; case " ebx": return Register32.EBX; case " ecx": return Register32.ECX; case " edx": return Register32.EDX; case " ebp": return Register32.EBP; case " esp": return Register32.ESP; case " esi": return Register32.ESI; case " edi": return Register32.EDI; default: return Register32.NONE; } } #endregion #region CompleteRegisters32 /// /// Checks all values of a Registers32 enum and returns false if any of them are not set. /// /// The Registers32 object to be tested /// A boolean value is returned private bool CompleteRegisters32(Register32 regState) { bool complete = true; if (!regState.HasFlag(Register32.EAX)) { return false; } if (!regState.HasFlag(Register32.EBX)) { return false; } if (!regState.HasFlag(Register32.ECX)) { return false; } if (!regState.HasFlag(Register32.EDX)) { return false; } if (!regState.HasFlag(Register32.EBP)) { return false; } if (!regState.HasFlag(Register32.ESP)) { return false; } if (!regState.HasFlag(Register32.ESI)) { return false; } if (!regState.HasFlag(Register32.EDI)) { return false; } return complete; } #endregion #region Registers32 private enum Register32 : ushort { NONE = 0, [Description(" eax")] EAX = 1, [Description(" ebx")] EBX = 2, [Description(" ecx")] ECX = 4, [Description(" edx")] EDX = 8, [Description(" ebp")] EBP = 16, [Description(" esp")] ESP = 32, [Description(" esi")] ESI = 64, [Description(" edi")] EDI = 128 } #endregion #region Opcode List Holders /// /// Contains lists of instructions for specific registers. /// public class X86Lists { /// /// pushEax list. /// public Dictionary pushEax = new Dictionary(); /// /// pushEbx list. /// public Dictionary pushEbx = new Dictionary(); /// /// pushEcx list. /// public Dictionary pushEcx = new Dictionary(); /// /// pushEdx list. /// public Dictionary pushEdx = new Dictionary(); /// /// pushEsp list. /// public Dictionary pushEsp = new Dictionary(); /// /// pushEbp list. /// public Dictionary pushEbp = new Dictionary(); /// /// pushEsi list. /// public Dictionary pushEsi = new Dictionary(); /// /// pushEdi list. /// public Dictionary pushEdi = new Dictionary(); /// /// jmpEsp list. /// public Dictionary jmpEsp = new Dictionary(); /// /// callEsp list. /// public Dictionary callEsp = new Dictionary(); /// /// xorEax list. /// public Dictionary xorEax = new Dictionary(); /// /// xorEbx list. /// public Dictionary xorEbx = new Dictionary(); /// /// xorEcx list. /// public Dictionary xorEcx = new Dictionary(); /// /// xorEdx list. /// public Dictionary xorEdx = new Dictionary(); /// /// xorEsi list. /// public Dictionary xorEsi = new Dictionary(); /// /// xorEdi list. /// public Dictionary xorEdi = new Dictionary(); /// /// popEax list. /// public Dictionary popEax = new Dictionary(); /// /// popEbx list. /// public Dictionary popEbx = new Dictionary(); /// /// popEcx list. /// public Dictionary popEcx = new Dictionary(); /// /// popEdx list. /// public Dictionary popEdx = new Dictionary(); /// /// popEsp list. /// public Dictionary popEsp = new Dictionary(); /// /// popEbp list. /// public Dictionary popEbp = new Dictionary(); /// /// popEsi list. /// public Dictionary popEsi = new Dictionary(); /// /// popEdi list. /// public Dictionary popEdi = new Dictionary(); /// /// pushad list. /// public Dictionary pushad = new Dictionary(); /// /// incEax list. /// public Dictionary incEax = new Dictionary(); /// /// incEbx list. /// public Dictionary incEbx = new Dictionary(); /// /// incEcx list. /// public Dictionary incEcx = new Dictionary(); /// /// incEdx list. /// public Dictionary incEdx = new Dictionary(); /// /// incEbp list. /// public Dictionary incEbp = new Dictionary(); /// /// incEsp list. /// public Dictionary incEsp = new Dictionary(); /// /// incEsi list. /// public Dictionary incEsi = new Dictionary(); /// /// incEdi list. /// public Dictionary incEdi = new Dictionary(); /// /// decEax list. /// public Dictionary decEax = new Dictionary(); /// /// decEbx list. /// public Dictionary decEbx = new Dictionary(); /// /// decEcx list. /// public Dictionary decEcx = new Dictionary(); /// /// decEdx list. /// public Dictionary decEdx = new Dictionary(); /// /// decEbp list. /// public Dictionary decEbp = new Dictionary(); /// /// decEsp list. /// public Dictionary decEsp = new Dictionary(); /// /// decEsi list. /// public Dictionary decEsi = new Dictionary(); /// /// decEdi list. /// public Dictionary decEdi = new Dictionary(); /// /// add list. /// public Dictionary add = new Dictionary(); /// /// sub list. /// public Dictionary sub = new Dictionary(); /// /// mov list. /// public Dictionary mov = new Dictionary(); /// /// and list. /// public Dictionary and = new Dictionary(); } #endregion private class RegisterModifiers32 { public Register32 EAX; public Register32 EBX; public Register32 ECX; public Register32 EDX; public Register32 EBP; public Register32 ESP; public Register32 ESI; public Register32 EDI; } private class RegisterLists32 { public List> eaxList = new List>(); public List> ebxList = new List>(); public List> ecxList = new List>(); public List> edxList = new List>(); public List> ebpList = new List>(); public List> espList = new List>(); public List> esiList = new List>(); public List> ediList = new List>(); } /// /// Enum of methods which can be used to generate a ROP chain. /// [Flags] public enum RopMethod : ushort { [Description(" VirtualAlloc")] VirtualAlloc = 1, [Description(" HeapCreate")] HeapCreate = 2, [Description(" VirtualProtect")] VirtualProtect = 4, [Description(" WriteProcessMemory")] WriteProcessMemory = 8, [Description(" All")] All = 15 } } } ================================================ FILE: ERC/ERC/RopChainGenerator64.cs ================================================ using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Runtime.InteropServices; namespace ERC.Utilities { /// Attempts to create Rop chains from 64 bit processes. public class RopChainGenerator64 { #region Class Variables private const int MEM_COMMIT = 0x1000; /// /// Contains a ROP chain which calls the VirtualAlloc method. /// public List> VirtualAllocChain = new List>(); /// /// Contains a ROP chain which calls the VirtualAlloc method. /// public List> HeapCreateChain = new List>(); /// /// Contains a ROP chain which calls the VirtualAlloc method. /// public List> VirtualProtectChain = new List>(); /// /// Contains a ROP chain which calls the VirtualAlloc method. /// public List> WriteProcessMemoryChain = new List>(); RopMethod Methods; internal X64Lists x64Opcodes; internal X64Lists usableX64Opcodes; internal ProcessInfo RcgInfo; private Dictionary ApiAddresses = new Dictionary(); private List RopNops = new List(); private List opcodes64 = new List(); #endregion #region Constructor /// /// Constructor /// /// ProcessInfo object for which a ROP chain will be generated public RopChainGenerator64(ProcessInfo _info) { if (_info.ProcessMachineType == MachineType.x64) { x64Opcodes = new X64Lists(); } else { throw new ArgumentException("Fatal Error: This is not a 64bit process."); } RcgInfo = _info; byte[] pushRax = new byte[] { 0x50 }; byte[] pushRcx = new byte[] { 0x51 }; byte[] pushRdx = new byte[] { 0x51 }; byte[] pushRbx = new byte[] { 0x53 }; byte[] pushRsp = new byte[] { 0x54 }; byte[] pushRbp = new byte[] { 0x55 }; byte[] pushRsi = new byte[] { 0x56 }; byte[] pushRdi = new byte[] { 0x57 }; byte[] pushR8 = new byte[] { 0x41, 0x50 }; byte[] pushR9 = new byte[] { 0x41, 0x51 }; byte[] pushR10 = new byte[] { 0x41, 0x52 }; byte[] pushR11 = new byte[] { 0x41, 0x53 }; byte[] pushR12 = new byte[] { 0x41, 0x54 }; byte[] pushR13 = new byte[] { 0x41, 0x55 }; byte[] pushR14 = new byte[] { 0x41, 0x56 }; byte[] pushR15 = new byte[] { 0x41, 0x57 }; byte[] popRax = new byte[] { 0x58 }; byte[] popRbx = new byte[] { 0x5B }; byte[] popRcx = new byte[] { 0x59 }; byte[] popRdx = new byte[] { 0x5A }; byte[] popRsp = new byte[] { 0x5C }; byte[] popRbp = new byte[] { 0x5D }; byte[] popRsi = new byte[] { 0x5E }; byte[] popRdi = new byte[] { 0x5F }; byte[] popR8 = new byte[] { 0x41, 0x58 }; byte[] popR9 = new byte[] { 0x41, 0x59 }; byte[] popR10 = new byte[] { 0x41, 0x5A }; byte[] popR11 = new byte[] { 0x41, 0x5B }; byte[] popR12 = new byte[] { 0x41, 0x5C }; byte[] popR13 = new byte[] { 0x41, 0x5D }; byte[] popR14 = new byte[] { 0x41, 0x5E }; byte[] popR15 = new byte[] { 0x41, 0x5F }; byte[] xorRax = new byte[] { 0x48, 0x31, 0xC0 }; byte[] xorRbx = new byte[] { 0x48, 0x31, 0xD8 }; byte[] xorRcx = new byte[] { 0x48, 0x31, 0xC9 }; byte[] xorRdx = new byte[] { 0x48, 0x31, 0xD2 }; byte[] xorRsi = new byte[] { 0x48, 0x31, 0xF6 }; byte[] xorRdi = new byte[] { 0x48, 0x31, 0xFF }; byte[] xorRsp = new byte[] { 0x48, 0x31, 0xE4 }; byte[] xorRbp = new byte[] { 0x48, 0x31, 0xED }; byte[] xorR8 = new byte[] { 0x48, 0x31, 0xC8 }; byte[] xorR9 = new byte[] { 0x48, 0x31, 0xC9 }; byte[] xorR10 = new byte[] { 0x48, 0x31, 0xD2 }; byte[] xorR11 = new byte[] { 0x48, 0x31, 0xDB }; byte[] xorR12 = new byte[] { 0x48, 0x31, 0xE4 }; byte[] xorR13 = new byte[] { 0x48, 0x31, 0xED }; byte[] xorR14 = new byte[] { 0x48, 0x31, 0xF6 }; byte[] xorR15 = new byte[] { 0x48, 0x31, 0xFF }; byte[] jmpRsp = new byte[] { 0xFF, 0xE4 }; byte[] callRsp = new byte[] { 0xFF, 0xD4 }; byte[] incRax = new byte[] { 0x48, 0xFF, 0xC0}; byte[] incRbx = new byte[] { 0x48, 0xFF, 0xC3 }; byte[] incRcx = new byte[] { 0x48, 0xFF, 0xC1 }; byte[] incRdx = new byte[] { 0x48, 0xFF, 0xC2 }; byte[] incRbp = new byte[] { 0x48, 0xFF, 0xC5 }; byte[] incRsp = new byte[] { 0x48, 0xFF, 0xC4 }; byte[] incRsi = new byte[] { 0x48, 0xFF, 0xC6 }; byte[] incRdi = new byte[] { 0x48, 0xFF, 0xC7 }; byte[] incR8 = new byte[] { 0x49, 0xFF, 0xC0 }; byte[] incR9 = new byte[] { 0x49, 0xFF, 0xC1 }; byte[] incR10 = new byte[] { 0x49, 0xFF, 0xC2 }; byte[] incR11 = new byte[] { 0x49, 0xFF, 0xC3 }; byte[] incR12 = new byte[] { 0x49, 0xFF, 0xC4 }; byte[] incR13 = new byte[] { 0x49, 0xFF, 0xC5 }; byte[] incR14 = new byte[] { 0x49, 0xFF, 0xC6 }; byte[] incR15 = new byte[] { 0x49, 0xFF, 0xC7 }; byte[] decRax = new byte[] { 0x48, 0xFF, 0xC8 }; byte[] decRbx = new byte[] { 0x48, 0xFF, 0xCB }; byte[] decRcx = new byte[] { 0x48, 0xFF, 0xC9 }; byte[] decRdx = new byte[] { 0x48, 0xFF, 0xCA }; byte[] decRbp = new byte[] { 0x48, 0xFF, 0xCD }; byte[] decRsp = new byte[] { 0x48, 0xFF, 0xCC }; byte[] decRsi = new byte[] { 0x48, 0xFF, 0xCE }; byte[] decRdi = new byte[] { 0x48, 0xFF, 0xCF }; byte[] decR8 = new byte[] { 0x49, 0xFF, 0xC8 }; byte[] decR9 = new byte[] { 0x49, 0xFF, 0xC9 }; byte[] decR10 = new byte[] { 0x49, 0xFF, 0xCA }; byte[] decR11 = new byte[] { 0x49, 0xFF, 0xCB }; byte[] decR12 = new byte[] { 0x49, 0xFF, 0xCC }; byte[] decR13 = new byte[] { 0x49, 0xFF, 0xCD }; byte[] decR14 = new byte[] { 0x49, 0xFF, 0xCE }; byte[] decR15 = new byte[] { 0x49, 0xFF, 0xCF }; byte[] add1 = new byte[] { 0x48, 0x01 }; byte[] add2 = new byte[] { 0x4C, 0x01 }; byte[] add3 = new byte[] { 0x49, 0x01 }; byte[] add4 = new byte[] { 0x4D, 0x01 }; byte[] mov1 = new byte[] { 0x48, 0x89 }; byte[] mov2 = new byte[] { 0x4C, 0x89 }; byte[] mov3 = new byte[] { 0x49, 0x89 }; byte[] mov4 = new byte[] { 0x4D, 0x89 }; byte[] sub1 = new byte[] { 0x48, 0x29 }; byte[] sub2 = new byte[] { 0x4C, 0x29 }; byte[] sub3 = new byte[] { 0x49, 0x29 }; byte[] sub4 = new byte[] { 0x4D, 0x29 }; byte[] jmpRax = new byte[] { 0xFF, 0xD0 }; byte[] callRax = new byte[] { 0xFF, 0xE0 }; opcodes64.Add(pushRax); opcodes64.Add(pushRcx); opcodes64.Add(pushRdx); opcodes64.Add(pushRbx); opcodes64.Add(pushRsp); opcodes64.Add(pushRbp); opcodes64.Add(pushRsi); opcodes64.Add(pushRdi); opcodes64.Add(pushR8); opcodes64.Add(pushR9); opcodes64.Add(pushR10); opcodes64.Add(pushR11); opcodes64.Add(pushR12); opcodes64.Add(pushR13); opcodes64.Add(pushR14); opcodes64.Add(pushR15); opcodes64.Add(popRax); opcodes64.Add(popRbx); opcodes64.Add(popRcx); opcodes64.Add(popRdx); opcodes64.Add(popRsp); opcodes64.Add(popRbp); opcodes64.Add(popRsi); opcodes64.Add(popRdi); opcodes64.Add(popR8); opcodes64.Add(popR9); opcodes64.Add(popR10); opcodes64.Add(popR11); opcodes64.Add(popR12); opcodes64.Add(popR13); opcodes64.Add(popR14); opcodes64.Add(popR15); opcodes64.Add(xorRax); opcodes64.Add(xorRbx); opcodes64.Add(xorRcx); opcodes64.Add(xorRdx); opcodes64.Add(xorRsi); opcodes64.Add(xorRdi); opcodes64.Add(xorRsp); opcodes64.Add(xorRbp); opcodes64.Add(xorR8); opcodes64.Add(xorR9); opcodes64.Add(xorR10); opcodes64.Add(xorR11); opcodes64.Add(xorR12); opcodes64.Add(xorR13); opcodes64.Add(xorR14); opcodes64.Add(xorR15); opcodes64.Add(jmpRsp); opcodes64.Add(callRsp); opcodes64.Add(incRax); opcodes64.Add(incRbx); opcodes64.Add(incRcx); opcodes64.Add(incRdx); opcodes64.Add(incRbp); opcodes64.Add(incRsp); opcodes64.Add(incRsi); opcodes64.Add(incRdi); opcodes64.Add(incR8); opcodes64.Add(incR9); opcodes64.Add(incR10); opcodes64.Add(incR11); opcodes64.Add(incR12); opcodes64.Add(incR13); opcodes64.Add(incR14); opcodes64.Add(incR15); opcodes64.Add(decRax); opcodes64.Add(decRbx); opcodes64.Add(decRcx); opcodes64.Add(decRdx); opcodes64.Add(decRbp); opcodes64.Add(decRsp); opcodes64.Add(decRsi); opcodes64.Add(decRdi); opcodes64.Add(decR8); opcodes64.Add(decR9); opcodes64.Add(decR10); opcodes64.Add(decR11); opcodes64.Add(decR12); opcodes64.Add(decR13); opcodes64.Add(decR14); opcodes64.Add(decR15); opcodes64.Add(add1); opcodes64.Add(add2); opcodes64.Add(add3); opcodes64.Add(add4); opcodes64.Add(mov1); opcodes64.Add(mov2); opcodes64.Add(mov3); opcodes64.Add(mov4); opcodes64.Add(sub1); opcodes64.Add(sub2); opcodes64.Add(sub3); opcodes64.Add(sub4); opcodes64.Add(jmpRax); opcodes64.Add(callRax); } #endregion #region GenerateRopGadgets64 /// /// Creates a list of ROP gadgets for a specific process. /// /// Takes a byte array of values used to disqualify ROP gadgets /// A list of modules to be excluded from the search for ROP gadgets /// Returns an ErcResult string containing public ErcResult GenerateRopGadgets64(byte[] ptrsToExclude = null, List excludes = null) { ErcResult RopChain = new ErcResult(RcgInfo.ProcessCore); x64Opcodes = new X64Lists(); var ret1 = GetApiAddresses(RcgInfo); if (ret1.Error != null && ApiAddresses.Count <= 0) { ErcResult failed = new ErcResult(RcgInfo.ProcessCore); failed.ReturnValue = "An error has occured, check log file for more details."; failed.Error = ret1.Error; } var ret2 = GetRopNops(RcgInfo, excludes); if (ret2.Error != null && RopNops.Count <= 0) { ErcResult failed = new ErcResult(RcgInfo.ProcessCore); failed.ReturnValue = "An error has occured, check log file for more details."; failed.Error = ret2.Error; } var ret3 = PopulateOpcodes(RcgInfo); if (ret3.Error != null) { ErcResult failed = new ErcResult(RcgInfo.ProcessCore); failed.ReturnValue = "An error has occured, check log file for more details."; failed.Error = ret3.Error; } OptimiseLists(RcgInfo); usableX64Opcodes.pushRax = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.pushRax, ptrsToExclude); usableX64Opcodes.pushRcx = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.pushRcx, ptrsToExclude); usableX64Opcodes.pushRdx = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.pushRdx, ptrsToExclude); usableX64Opcodes.pushRbx = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.pushRbx, ptrsToExclude); usableX64Opcodes.pushRsp = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.pushRsp, ptrsToExclude); usableX64Opcodes.pushRbp = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.pushRbp, ptrsToExclude); usableX64Opcodes.pushRsi = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.pushRsi, ptrsToExclude); usableX64Opcodes.pushRdi = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.pushRdi, ptrsToExclude); usableX64Opcodes.pushR8 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.pushR8, ptrsToExclude); usableX64Opcodes.pushR9 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.pushR9, ptrsToExclude); usableX64Opcodes.pushR10 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.pushR10, ptrsToExclude); usableX64Opcodes.pushR11 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.pushR11, ptrsToExclude); usableX64Opcodes.pushR12 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.pushR12, ptrsToExclude); usableX64Opcodes.pushR13 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.pushR13, ptrsToExclude); usableX64Opcodes.pushR14 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.pushR14, ptrsToExclude); usableX64Opcodes.pushR15 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.pushR15, ptrsToExclude); usableX64Opcodes.popRax = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.popRax, ptrsToExclude); usableX64Opcodes.popRbx = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.popRbx, ptrsToExclude); usableX64Opcodes.popRcx = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.popRcx, ptrsToExclude); usableX64Opcodes.popRdx = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.popRdx, ptrsToExclude); usableX64Opcodes.popRsp = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.popRsp, ptrsToExclude); usableX64Opcodes.popRbp = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.popRbp, ptrsToExclude); usableX64Opcodes.popRsi = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.popRsi, ptrsToExclude); usableX64Opcodes.popRdi = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.popRdi, ptrsToExclude); usableX64Opcodes.popR8 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.popR8, ptrsToExclude); usableX64Opcodes.popR9 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.popR9, ptrsToExclude); usableX64Opcodes.popR10 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.popR10, ptrsToExclude); usableX64Opcodes.popR11 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.popR11, ptrsToExclude); usableX64Opcodes.popR12 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.popR12, ptrsToExclude); usableX64Opcodes.popR13 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.popR13, ptrsToExclude); usableX64Opcodes.popR14 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.popR14, ptrsToExclude); usableX64Opcodes.popR15 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.popR15, ptrsToExclude); usableX64Opcodes.xorRax = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.xorRax, ptrsToExclude); usableX64Opcodes.xorRbx = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.xorRbx, ptrsToExclude); usableX64Opcodes.xorRcx = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.xorRcx, ptrsToExclude); usableX64Opcodes.xorRdx = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.xorRdx, ptrsToExclude); usableX64Opcodes.xorRsi = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.xorRsi, ptrsToExclude); usableX64Opcodes.xorRdi = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.xorRdi, ptrsToExclude); usableX64Opcodes.xorRsp = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.xorRsp, ptrsToExclude); usableX64Opcodes.xorRbp = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.xorRbp, ptrsToExclude); usableX64Opcodes.xorR8 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.xorR8, ptrsToExclude); usableX64Opcodes.xorR9 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.xorR9, ptrsToExclude); usableX64Opcodes.xorR10 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.xorR10, ptrsToExclude); usableX64Opcodes.xorR11 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.xorR11, ptrsToExclude); usableX64Opcodes.xorR12 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.xorR12, ptrsToExclude); usableX64Opcodes.xorR13 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.xorR13, ptrsToExclude); usableX64Opcodes.xorR14 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.xorR14, ptrsToExclude); usableX64Opcodes.xorR15 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.xorR15, ptrsToExclude); usableX64Opcodes.jmpRsp = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.jmpRsp, ptrsToExclude); usableX64Opcodes.callRsp = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.callRsp, ptrsToExclude); usableX64Opcodes.incRax = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.incRax, ptrsToExclude); usableX64Opcodes.incRbx = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.incRbx, ptrsToExclude); usableX64Opcodes.incRcx = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.incRcx, ptrsToExclude); usableX64Opcodes.incRdx = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.incRdx, ptrsToExclude); usableX64Opcodes.incRbp = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.incRbp, ptrsToExclude); usableX64Opcodes.incRsp = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.incRsp, ptrsToExclude); usableX64Opcodes.incRsi = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.incRsi, ptrsToExclude); usableX64Opcodes.incRdi = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.incRdi, ptrsToExclude); usableX64Opcodes.incR8 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.incR8, ptrsToExclude); usableX64Opcodes.incR9 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.incR9, ptrsToExclude); usableX64Opcodes.incR10 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.incR10, ptrsToExclude); usableX64Opcodes.incR11 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.incR11, ptrsToExclude); usableX64Opcodes.incR12 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.incR12, ptrsToExclude); usableX64Opcodes.incR13 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.incR13, ptrsToExclude); usableX64Opcodes.incR14 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.incR14, ptrsToExclude); usableX64Opcodes.incR15 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.incR15, ptrsToExclude); usableX64Opcodes.decRax = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.decRax, ptrsToExclude); usableX64Opcodes.decRbx = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.decRbx, ptrsToExclude); usableX64Opcodes.decRcx = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.decRcx, ptrsToExclude); usableX64Opcodes.decRdx = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.decRdx, ptrsToExclude); usableX64Opcodes.decRbp = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.decRbp, ptrsToExclude); usableX64Opcodes.decRsp = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.decRsp, ptrsToExclude); usableX64Opcodes.decRsi = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.decRsi, ptrsToExclude); usableX64Opcodes.decRdi = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.decRdi, ptrsToExclude); usableX64Opcodes.decR8 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.decR8, ptrsToExclude); usableX64Opcodes.decR9 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.decR9, ptrsToExclude); usableX64Opcodes.decR10 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.decR10, ptrsToExclude); usableX64Opcodes.decR11 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.decR11, ptrsToExclude); usableX64Opcodes.decR12 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.decR12, ptrsToExclude); usableX64Opcodes.decR13 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.decR13, ptrsToExclude); usableX64Opcodes.decR14 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.decR14, ptrsToExclude); usableX64Opcodes.decR15 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.decR15, ptrsToExclude); usableX64Opcodes.add = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.add, ptrsToExclude); usableX64Opcodes.mov = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.mov, ptrsToExclude); usableX64Opcodes.sub = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.sub, ptrsToExclude); DisplayOutput.RopChainGadgets64(this, true); return RopChain; } #endregion #region GenerateRopChain64 /// /// Creates a RopChain for a specific process. /// /// Takes a byte array of values used to disqualify ROP gadgets /// A Address to be used as the start location for which memory will be made executable /// A list of modules to be excluded from the search for ROP gadgets /// Returns an ErcResult string containing public ErcResult GenerateRopChain64(byte[] ptrsToExclude, byte[] startAddress = null, List excludes = null, RopMethod methods = RopMethod.All) { Methods = methods; ErcResult RopChain = new ErcResult(RcgInfo.ProcessCore); x64Opcodes = new X64Lists(); var ret1 = GetApiAddresses(RcgInfo); if (ret1.Error != null && ApiAddresses.Count <= 0) { ErcResult failed = new ErcResult(RcgInfo.ProcessCore); failed.ReturnValue = "An error has occured, check log file for more details."; failed.Error = ret1.Error; } if (excludes != null) { var ret2 = GetRopNops(RcgInfo, excludes); if (ret2.Error != null && RopNops.Count <= 0) { ErcResult failed = new ErcResult(RcgInfo.ProcessCore); failed.ReturnValue = "An error has occured, check log file for more details."; failed.Error = ret2.Error; return failed; } } else { var ret2 = GetRopNops(RcgInfo); if (ret2.Error != null && RopNops.Count <= 0) { ErcResult failed = new ErcResult(RcgInfo.ProcessCore); failed.ReturnValue = "An error has occured, check log file for more details."; failed.Error = ret2.Error; return failed; } } var ret3 = PopulateOpcodes(RcgInfo); if (ret3.Error != null) { ErcResult failed = new ErcResult(RcgInfo.ProcessCore); failed.ReturnValue = "An error has occured, check log file for more details."; failed.Error = ret3.Error; } OptimiseLists(RcgInfo); usableX64Opcodes.pushRax = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.pushRax, ptrsToExclude); usableX64Opcodes.pushRcx = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.pushRcx, ptrsToExclude); usableX64Opcodes.pushRdx = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.pushRdx, ptrsToExclude); usableX64Opcodes.pushRbx = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.pushRbx, ptrsToExclude); usableX64Opcodes.pushRsp = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.pushRsp, ptrsToExclude); usableX64Opcodes.pushRbp = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.pushRbp, ptrsToExclude); usableX64Opcodes.pushRsi = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.pushRsi, ptrsToExclude); usableX64Opcodes.pushRdi = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.pushRdi, ptrsToExclude); usableX64Opcodes.pushR8 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.pushR8, ptrsToExclude); usableX64Opcodes.pushR9 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.pushR9, ptrsToExclude); usableX64Opcodes.pushR10 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.pushR10, ptrsToExclude); usableX64Opcodes.pushR11 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.pushR11, ptrsToExclude); usableX64Opcodes.pushR12 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.pushR12, ptrsToExclude); usableX64Opcodes.pushR13 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.pushR13, ptrsToExclude); usableX64Opcodes.pushR14 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.pushR14, ptrsToExclude); usableX64Opcodes.pushR15 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.pushR15, ptrsToExclude); usableX64Opcodes.popRax = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.popRax, ptrsToExclude); usableX64Opcodes.popRbx = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.popRbx, ptrsToExclude); usableX64Opcodes.popRcx = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.popRcx, ptrsToExclude); usableX64Opcodes.popRdx = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.popRdx, ptrsToExclude); usableX64Opcodes.popRsp = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.popRsp, ptrsToExclude); usableX64Opcodes.popRbp = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.popRbp, ptrsToExclude); usableX64Opcodes.popRsi = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.popRsi, ptrsToExclude); usableX64Opcodes.popRdi = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.popRdi, ptrsToExclude); usableX64Opcodes.popR8 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.popR8, ptrsToExclude); usableX64Opcodes.popR9 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.popR9, ptrsToExclude); usableX64Opcodes.popR10 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.popR10, ptrsToExclude); usableX64Opcodes.popR11 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.popR11, ptrsToExclude); usableX64Opcodes.popR12 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.popR12, ptrsToExclude); usableX64Opcodes.popR13 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.popR13, ptrsToExclude); usableX64Opcodes.popR14 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.popR14, ptrsToExclude); usableX64Opcodes.popR15 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.popR15, ptrsToExclude); usableX64Opcodes.xorRax = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.xorRax, ptrsToExclude); usableX64Opcodes.xorRbx = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.xorRbx, ptrsToExclude); usableX64Opcodes.xorRcx = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.xorRcx, ptrsToExclude); usableX64Opcodes.xorRdx = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.xorRdx, ptrsToExclude); usableX64Opcodes.xorRsi = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.xorRsi, ptrsToExclude); usableX64Opcodes.xorRdi = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.xorRdi, ptrsToExclude); usableX64Opcodes.xorRsp = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.xorRsp, ptrsToExclude); usableX64Opcodes.xorRbp = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.xorRbp, ptrsToExclude); usableX64Opcodes.xorR8 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.xorR8, ptrsToExclude); usableX64Opcodes.xorR9 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.xorR9, ptrsToExclude); usableX64Opcodes.xorR10 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.xorR10, ptrsToExclude); usableX64Opcodes.xorR11 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.xorR11, ptrsToExclude); usableX64Opcodes.xorR12 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.xorR12, ptrsToExclude); usableX64Opcodes.xorR13 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.xorR13, ptrsToExclude); usableX64Opcodes.xorR14 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.xorR14, ptrsToExclude); usableX64Opcodes.xorR15 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.xorR15, ptrsToExclude); usableX64Opcodes.jmpRsp = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.jmpRsp, ptrsToExclude); usableX64Opcodes.callRsp = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.callRsp, ptrsToExclude); usableX64Opcodes.incRax = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.incRax, ptrsToExclude); usableX64Opcodes.incRbx = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.incRbx, ptrsToExclude); usableX64Opcodes.incRcx = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.incRcx, ptrsToExclude); usableX64Opcodes.incRdx = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.incRdx, ptrsToExclude); usableX64Opcodes.incRbp = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.incRbp, ptrsToExclude); usableX64Opcodes.incRsp = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.incRsp, ptrsToExclude); usableX64Opcodes.incRsi = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.incRsi, ptrsToExclude); usableX64Opcodes.incRdi = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.incRdi, ptrsToExclude); usableX64Opcodes.incR8 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.incR8, ptrsToExclude); usableX64Opcodes.incR9 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.incR9, ptrsToExclude); usableX64Opcodes.incR10 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.incR10, ptrsToExclude); usableX64Opcodes.incR11 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.incR11, ptrsToExclude); usableX64Opcodes.incR12 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.incR12, ptrsToExclude); usableX64Opcodes.incR13 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.incR13, ptrsToExclude); usableX64Opcodes.incR14 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.incR14, ptrsToExclude); usableX64Opcodes.incR15 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.incR15, ptrsToExclude); usableX64Opcodes.decRax = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.decRax, ptrsToExclude); usableX64Opcodes.decRbx = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.decRbx, ptrsToExclude); usableX64Opcodes.decRcx = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.decRcx, ptrsToExclude); usableX64Opcodes.decRdx = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.decRdx, ptrsToExclude); usableX64Opcodes.decRbp = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.decRbp, ptrsToExclude); usableX64Opcodes.decRsp = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.decRsp, ptrsToExclude); usableX64Opcodes.decRsi = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.decRsi, ptrsToExclude); usableX64Opcodes.decRdi = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.decRdi, ptrsToExclude); usableX64Opcodes.decR8 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.decR8, ptrsToExclude); usableX64Opcodes.decR9 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.decR9, ptrsToExclude); usableX64Opcodes.decR10 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.decR10, ptrsToExclude); usableX64Opcodes.decR11 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.decR11, ptrsToExclude); usableX64Opcodes.decR12 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.decR12, ptrsToExclude); usableX64Opcodes.decR13 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.decR13, ptrsToExclude); usableX64Opcodes.decR14 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.decR14, ptrsToExclude); usableX64Opcodes.decR15 = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.decR15, ptrsToExclude); usableX64Opcodes.add = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.add, ptrsToExclude); usableX64Opcodes.mov = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.mov, ptrsToExclude); usableX64Opcodes.sub = PtrRemover.RemovePointers(RcgInfo.ProcessMachineType, usableX64Opcodes.sub, ptrsToExclude); if (Methods.HasFlag(RopMethod.VirtualAlloc)) { var vpaChain = GenerateVirtualAllocChain64(RcgInfo); if (vpaChain.Error == null) { VirtualAllocChain = vpaChain.ReturnValue; } } if (Methods.HasFlag(RopMethod.HeapCreate)) { var hcChain = GenerateHeapCreateChain64(RcgInfo); if (hcChain.Error == null) { HeapCreateChain = hcChain.ReturnValue; } } if (Methods.HasFlag(RopMethod.VirtualProtect)) { var vpChain = GenerateVirtualProtectChain64(RcgInfo); if (vpChain.Error == null) { VirtualProtectChain = vpChain.ReturnValue; } } var output = DisplayOutput.RopChainGadgets64(this); RopChain.ReturnValue = String.Join("\n", output); return RopChain; } /// /// Creates a RopChain for a specific process. /// /// A Address to be used as the start location for which memory will be made executable /// A list of modules to be excluded from the search for ROP gadgets /// Returns an ErcResult string containing public ErcResult GenerateRopChain64(byte[] startAddress = null, List excludes = null, RopMethod methods = RopMethod.All) { Methods = methods; ErcResult RopChain = new ErcResult(RcgInfo.ProcessCore); x64Opcodes = new X64Lists(); Console.WriteLine("Getting API Addresses..."); var ret1 = GetApiAddresses(RcgInfo); if (ret1.Error != null && ApiAddresses.Count <= 0) { ErcResult failed = new ErcResult(RcgInfo.ProcessCore); failed.ReturnValue = "An error has occured, check log file for more details."; failed.Error = ret1.Error; } Console.WriteLine("Getting RopNops..."); if(excludes != null) { var ret2 = GetRopNops(RcgInfo, excludes); if (ret2.Error != null && RopNops.Count <= 0) { ErcResult failed = new ErcResult(RcgInfo.ProcessCore); failed.ReturnValue = "An error has occured, check log file for more details."; failed.Error = ret2.Error; return failed; } } else { var ret2 = GetRopNops(RcgInfo); if (ret2.Error != null && RopNops.Count <= 0) { ErcResult failed = new ErcResult(RcgInfo.ProcessCore); failed.ReturnValue = "An error has occured, check log file for more details."; failed.Error = ret2.Error; return failed; } } Console.WriteLine("Populating Opcodes..."); var ret3 = PopulateOpcodes(RcgInfo); if (ret3.Error != null) { ErcResult failed = new ErcResult(RcgInfo.ProcessCore); failed.ReturnValue = "An error has occured, check log file for more details."; failed.Error = ret3.Error; } Console.WriteLine("Optimizing Lists..."); OptimiseLists(RcgInfo); Console.WriteLine("Generating VirtualAlloc Chain..."); if (Methods.HasFlag(RopMethod.VirtualAlloc)) { var vpaChain = GenerateVirtualAllocChain64(RcgInfo); if (vpaChain.Error == null) { VirtualAllocChain = vpaChain.ReturnValue; } } Console.WriteLine("Generating HeapCreate Chain..."); if (Methods.HasFlag(RopMethod.HeapCreate)) { var hcChain = GenerateHeapCreateChain64(RcgInfo); if (hcChain.Error == null) { HeapCreateChain = hcChain.ReturnValue; } } if (Methods.HasFlag(RopMethod.VirtualProtect)) { var vpChain = GenerateVirtualProtectChain64(RcgInfo); if (vpChain.Error == null) { VirtualProtectChain = vpChain.ReturnValue; } } var output = DisplayOutput.RopChainGadgets64(this); RopChain.ReturnValue = String.Join("\n", output); return RopChain; } #endregion #region GetApiAddresses private ErcResult GetApiAddresses(ProcessInfo info) { ErcResult returnVar = new ErcResult(info.ProcessCore); returnVar.ReturnValue = 0; IntPtr hModule = IntPtr.Zero; for (int i = 0; i < info.ModulesInfo.Count; i++) { if (info.ModulesInfo[i].ModuleName == "kernel32") { hModule = info.ModulesInfo[i].ModuleBase; } } var virtAllocAddress = ErcCore.GetProcAddress(hModule, "VirtualAlloc"); if (virtAllocAddress == IntPtr.Zero) { returnVar.Error = new ERCException(new Win32Exception(Marshal.GetLastWin32Error()).Message); returnVar.LogEvent(); } else { ApiAddresses.Add("VirtualAlloc", virtAllocAddress); } var HeapCreateAddress = ErcCore.GetProcAddress(hModule, "HeapCreate"); if (HeapCreateAddress == IntPtr.Zero) { returnVar.Error = new ERCException(new Win32Exception(Marshal.GetLastWin32Error()).Message); returnVar.LogEvent(); } else { ApiAddresses.Add("HeapCreate", HeapCreateAddress); } var VirtualProtectAddress = ErcCore.GetProcAddress(hModule, "VirtualProtect"); if (VirtualProtectAddress == IntPtr.Zero) { returnVar.Error = new ERCException(new Win32Exception(Marshal.GetLastWin32Error()).Message); returnVar.LogEvent(); } else { ApiAddresses.Add("VirtualProtect", VirtualProtectAddress); } var WriteProcessMemoryAddress = ErcCore.GetProcAddress(hModule, "WriteProcessMemory"); if (WriteProcessMemoryAddress == IntPtr.Zero) { returnVar.Error = new ERCException(new Win32Exception(Marshal.GetLastWin32Error()).Message); returnVar.LogEvent(); } else { ApiAddresses.Add("WriteProcessMemory", WriteProcessMemoryAddress); } return returnVar; } #endregion #region GetRopNops private ErcResult> GetRopNops(ProcessInfo info, List excludes = null) { ErcResult> ropNopsResult = new ErcResult>(info.ProcessCore); ropNopsResult.ReturnValue = new List(); byte[] ropNop = new byte[] { 0xC3 }; var ropPtrs = RcgInfo.SearchModules(0, searchBytes: ropNop, excludedModules: excludes); if (ropPtrs.Error != null) { ropNopsResult.Error = ropPtrs.Error; } foreach (KeyValuePair k in ropPtrs.ReturnValue) { ropNopsResult.ReturnValue.Add(k.Key); RopNops.Add(k.Key); } return ropNopsResult; } private ErcResult> GetRopNops(ProcessInfo info) { ErcResult> ropNopsResult = new ErcResult>(info.ProcessCore); ropNopsResult.ReturnValue = new List(); byte[] ropNop = new byte[] { 0xC3 }; var ropPtrs = info.SearchModules(0, searchBytes: ropNop); if (ropPtrs.Error != null) { ropNopsResult.Error = ropPtrs.Error; } foreach (KeyValuePair k in ropPtrs.ReturnValue) { ropNopsResult.ReturnValue.Add(k.Key); RopNops.Add(k.Key); } return ropNopsResult; } #endregion #region PopulateOpcodes private ErcResult PopulateOpcodes(ProcessInfo info) { ErcResult ret = new ErcResult(info.ProcessCore); for (int i = 0; i < RopNops.Count; i++) { byte[] bytes = new byte[20]; IntPtr baseAddress = RopNops[i] - 19; ErcCore.ReadProcessMemory(info.ProcessHandle, baseAddress, bytes, 20, out int bytesRead); if (bytesRead != 20) { ret.Error = new ERCException("ReadProcessMemory Error: " + new Win32Exception(Marshal.GetLastWin32Error()).Message); ret.LogEvent(); } var ret1 = ParseByteArrayForRopCodes(bytes, info, baseAddress); if (ret1.Error != null) { ret.Error = ret1.Error; return ret; } } return ret; } #endregion #region ParseByteArrayForRopCodes private ErcResult ParseByteArrayForRopCodes(byte[] bytes, ProcessInfo info, IntPtr baseAddress) { ErcResult ret = new ErcResult(info.ProcessCore); bool pushRaxDone = false; bool pushRcxDone = false; bool pushRdxDone = false; bool pushRbxDone = false; bool pushRspDone = false; bool pushRbpDone = false; bool pushRsiDone = false; bool pushRdiDone = false; bool pushR8Done = false; bool pushR9Done = false; bool pushR10Done = false; bool pushR11Done = false; bool pushR12Done = false; bool pushR13Done = false; bool pushR14Done = false; bool pushR15Done = false; bool popRaxDone = false; bool popRbxDone = false; bool popRcxDone = false; bool popRdxDone = false; bool popRspDone = false; bool popRbpDone = false; bool popRsiDone = false; bool popRdiDone = false; bool popR8Done = false; bool popR9Done = false; bool popR10Done = false; bool popR11Done = false; bool popR12Done = false; bool popR13Done = false; bool popR14Done = false; bool popR15Done = false; bool xorRaxDone = false; bool xorRbxDone = false; bool xorRcxDone = false; bool xorRdxDone = false; bool xorRsiDone = false; bool xorRdiDone = false; bool xorRspDone = false; bool xorRbpDone = false; bool xorR8Done = false; bool xorR9Done = false; bool xorR10Done = false; bool xorR11Done = false; bool xorR12Done = false; bool xorR13Done = false; bool xorR14Done = false; bool xorR15Done = false; bool jmpRspDone = false; bool callRspDone = false; bool incRaxDone = false; bool incRbxDone = false; bool incRcxDone = false; bool incRdxDone = false; bool incRbpDone = false; bool incRspDone = false; bool incRsiDone = false; bool incRdiDone = false; bool incR8Done = false; bool incR9Done = false; bool incR10Done = false; bool incR11Done = false; bool incR12Done = false; bool incR13Done = false; bool incR14Done = false; bool incR15Done = false; bool decRaxDone = false; bool decRbxDone = false; bool decRcxDone = false; bool decRdxDone = false; bool decRbpDone = false; bool decRspDone = false; bool decRsiDone = false; bool decRdiDone = false; bool decR8Done = false; bool decR9Done = false; bool decR10Done = false; bool decR11Done = false; bool decR12Done = false; bool decR13Done = false; bool decR14Done = false; bool decR15Done = false; bool addDone = false; bool movDone = false; bool subDone = false; bool jmpRaxDone = false; bool callRaxDone = false; for (int i = bytes.Length - 1; i > 0; i--) { for (int j = 0; j < opcodes64.Count; j++) { if (bytes[i] == opcodes64[j][0] && opcodes64[j].Length == 1) { byte[] opcodes = new byte[bytes.Length - i]; switch (j) { case 0: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.pushRax.ContainsKey(baseAddress + i) && pushRaxDone == false) { pushRaxDone = true; x64Opcodes.pushRax.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 1: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.pushRbx.ContainsKey(baseAddress + i) && pushRbxDone == false) { pushRbxDone = true; x64Opcodes.pushRbx.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 2: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.pushRcx.ContainsKey(baseAddress + i) && pushRcxDone == false) { pushRcxDone = true; x64Opcodes.pushRcx.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 3: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.pushRdx.ContainsKey(baseAddress + i) && pushRdxDone == false) { pushRdxDone = true; x64Opcodes.pushRdx.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 4: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.pushRsp.ContainsKey(baseAddress + i) && pushRspDone == false) { pushRspDone = true; x64Opcodes.pushRsp.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 5: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.pushRbp.ContainsKey(baseAddress + i) && pushRbpDone == false) { pushRbpDone = true; x64Opcodes.pushRbp.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 6: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.pushRsi.ContainsKey(baseAddress + i) && pushRsiDone == false) { pushRsiDone = true; x64Opcodes.pushRsi.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 7: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.pushRdi.ContainsKey(baseAddress + i) && pushRdiDone == false) { pushRdiDone = true; x64Opcodes.pushRdi.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 16: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.popRax.ContainsKey(baseAddress + i) && popRaxDone == false) { popRaxDone = true; x64Opcodes.popRax.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 17: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.popRbx.ContainsKey(baseAddress + i) && popRbxDone == false) { popRbxDone = true; x64Opcodes.popRbx.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 18: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.popRcx.ContainsKey(baseAddress + i) && popRcxDone == false) { popRcxDone = true; x64Opcodes.popRcx.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 19: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.popRdx.ContainsKey(baseAddress + i) && popRdxDone == false) { popRdxDone = true; x64Opcodes.popRdx.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 20: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.popRsp.ContainsKey(baseAddress + i) && popRspDone == false) { popRspDone = true; x64Opcodes.popRsp.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 21: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.popRbp.ContainsKey(baseAddress + i) && popRbpDone == false) { popRbpDone = true; x64Opcodes.popRbp.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 22: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.popRsi.ContainsKey(baseAddress + i) && popRsiDone == false) { popRsiDone = true; x64Opcodes.popRsi.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 23: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.popRdi.ContainsKey(baseAddress + i) && popRdiDone == false) { popRdiDone = true; x64Opcodes.popRdi.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; default: ret.Error = new ERCException("An error has occured in RopChainGenerator.ParseByteArrayForRopCodes whilst parsing single length x64 instructions"); break; } } else if (opcodes64[j].Length == 2) { if (bytes[i] == opcodes64[j][0] && i < bytes.Length - 1 && j < opcodes64.Count + 1 && bytes[i + 1] == opcodes64[j][1]) { byte[] opcodes = new byte[bytes.Length - i]; switch (j) { case 8: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.pushR8.ContainsKey(baseAddress + i) && pushR8Done == false) { pushR8Done = true; x64Opcodes.pushR8.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 9: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.pushR9.ContainsKey(baseAddress + i) && pushR9Done == false) { pushR9Done = true; x64Opcodes.pushR9.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 10: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.pushR10.ContainsKey(baseAddress + i) && pushR10Done == false) { pushR10Done = true; x64Opcodes.pushR10.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 11: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.pushR11.ContainsKey(baseAddress + i) && pushR11Done == false) { pushR11Done = true; x64Opcodes.pushR11.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 12: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.pushR12.ContainsKey(baseAddress + i) && pushR12Done == false) { pushR12Done = true; x64Opcodes.pushR12.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 13: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.pushR13.ContainsKey(baseAddress + i) && pushR13Done == false) { pushR13Done = true; x64Opcodes.pushR13.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 14: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.pushR14.ContainsKey(baseAddress + i) && pushR14Done == false) { pushR14Done = true; x64Opcodes.pushR14.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 15: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.pushR15.ContainsKey(baseAddress + i) && pushR15Done == false) { pushR15Done = true; x64Opcodes.pushR15.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 24: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.popR8.ContainsKey(baseAddress + i) && popR8Done == false) { popR8Done = true; x64Opcodes.popR8.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 25: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.popR9.ContainsKey(baseAddress + i) && popR9Done == false) { popR9Done = true; x64Opcodes.popR9.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 26: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.popR10.ContainsKey(baseAddress + i) && popR10Done == false) { popR10Done = true; x64Opcodes.popR10.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 27: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.popR11.ContainsKey(baseAddress + i) && popR11Done == false) { popR11Done = true; x64Opcodes.popR11.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 28: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.popR12.ContainsKey(baseAddress + i) && popR12Done == false) { popR12Done = true; x64Opcodes.popR12.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 29: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.popR13.ContainsKey(baseAddress + i) && popR13Done == false) { popR13Done = true; x64Opcodes.popR13.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 30: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.popR14.ContainsKey(baseAddress + i) && popR14Done == false) { popR14Done = true; x64Opcodes.popR14.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 31: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.popR15.ContainsKey(baseAddress + i) && popR15Done == false) { popR15Done = true; x64Opcodes.popR15.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 48: opcodes = new byte[2]; Array.Copy(bytes, i, opcodes, 0, 2); if (!x64Opcodes.jmpRsp.ContainsKey(baseAddress + i) && jmpRspDone == false) { jmpRspDone = true; x64Opcodes.jmpRsp.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 49: opcodes = new byte[2]; Array.Copy(bytes, i, opcodes, 0, 2); if (!x64Opcodes.callRsp.ContainsKey(baseAddress + i) && callRspDone == false) { callRspDone = true; x64Opcodes.callRsp.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 82: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.add.ContainsKey(baseAddress + i) && addDone == false) { addDone = true; x64Opcodes.add.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 83: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.add.ContainsKey(baseAddress + i) && addDone == false) { addDone = true; x64Opcodes.add.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 84: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.add.ContainsKey(baseAddress + i) && addDone == false) { addDone = true; x64Opcodes.add.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 85: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.add.ContainsKey(baseAddress + i) && addDone == false) { addDone = true; x64Opcodes.add.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 86: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.mov.ContainsKey(baseAddress + i) && movDone == false) { movDone = true; x64Opcodes.mov.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 87: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.mov.ContainsKey(baseAddress + i) && movDone == false) { movDone = true; x64Opcodes.mov.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 88: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.mov.ContainsKey(baseAddress + i) && movDone == false) { movDone = true; x64Opcodes.mov.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 89: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.mov.ContainsKey(baseAddress + i) && movDone == false) { movDone = true; x64Opcodes.mov.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 90: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.sub.ContainsKey(baseAddress + i) && subDone == false) { subDone = true; x64Opcodes.sub.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 91: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.sub.ContainsKey(baseAddress + i) && subDone == false) { subDone = true; x64Opcodes.sub.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 92: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.sub.ContainsKey(baseAddress + i) && subDone == false) { subDone = true; x64Opcodes.sub.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 93: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.sub.ContainsKey(baseAddress + i) && subDone == false) { subDone = true; x64Opcodes.sub.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 94: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.callRax.ContainsKey(baseAddress + i) && callRaxDone == false) { callRaxDone = true; x64Opcodes.callRax.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 95: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.jmpRax.ContainsKey(baseAddress + i) && jmpRaxDone == false) { jmpRaxDone = true; x64Opcodes.jmpRax.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; default: ret.Error = new ERCException("An error has occured in RopChainGenerator.ParseByteArrayForRopCodes whilst parsing double length x64 instructions"); break; } } } else if (opcodes64[j].Length > 2) { if (bytes[i] == opcodes64[j][0] && i < bytes.Length - 2 && j < opcodes64.Count + 2 && bytes[i + 1] == opcodes64[j][1] && bytes[i + 2] == opcodes64[j][2]) { byte[] opcodes = new byte[bytes.Length - i]; switch (j) { case 50: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.incRax.ContainsKey(baseAddress + i) && incRaxDone == false) { incRaxDone = true; x64Opcodes.incRax.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 51: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.incRbx.ContainsKey(baseAddress + i) && incRbxDone == false) { incRbxDone = true; x64Opcodes.incRbx.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 52: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.incRcx.ContainsKey(baseAddress + i) && incRcxDone == false) { incRcxDone = true; x64Opcodes.incRcx.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 53: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.incRdx.ContainsKey(baseAddress + i) && incRdxDone == false) { incRdxDone = true; x64Opcodes.incRdx.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 54: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.incRbp.ContainsKey(baseAddress + i) && incRbpDone == false) { incRbpDone = true; x64Opcodes.incRbp.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 55: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.incRsp.ContainsKey(baseAddress + i) && incRspDone == false) { incRspDone = true; x64Opcodes.incRsp.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 56: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.incRsi.ContainsKey(baseAddress + i) && incRsiDone == false) { incRsiDone = true; x64Opcodes.incRsi.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 57: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.incRdi.ContainsKey(baseAddress + i) && incRdiDone == false) { incRdiDone = true; x64Opcodes.incRdi.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 58: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.incR8.ContainsKey(baseAddress + i) && incR8Done == false) { incR8Done = true; x64Opcodes.incR8.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 59: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.incR9.ContainsKey(baseAddress + i) && incR9Done == false) { incR9Done = true; x64Opcodes.incR9.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 60: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.incR10.ContainsKey(baseAddress + i) && incR10Done == false) { incR10Done = true; x64Opcodes.incR10.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 61: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.incR11.ContainsKey(baseAddress + i) && incR11Done == false) { incR11Done = true; x64Opcodes.incR11.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 62: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.incR12.ContainsKey(baseAddress + i) && incR12Done == false) { incR12Done = true; x64Opcodes.incR12.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 63: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.incR13.ContainsKey(baseAddress + i) && incR13Done == false) { incR13Done = true; x64Opcodes.incR13.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 64: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.incR14.ContainsKey(baseAddress + i) && incR14Done == false) { incR14Done = true; x64Opcodes.incR14.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 65: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.incR15.ContainsKey(baseAddress + i) && incR15Done == false) { incR15Done = true; x64Opcodes.incR15.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 66: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.decRax.ContainsKey(baseAddress + i) && decRaxDone == false) { decRaxDone = true; x64Opcodes.decRax.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 67: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.decRbx.ContainsKey(baseAddress + i) && decRbxDone == false) { decRbxDone = true; x64Opcodes.decRbx.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 68: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.decRcx.ContainsKey(baseAddress + i) && decRcxDone == false) { decRcxDone = true; x64Opcodes.decRcx.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 69: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.decRdx.ContainsKey(baseAddress + i) && decRdxDone == false) { decRdxDone = true; x64Opcodes.decRdx.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 70: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.decRbp.ContainsKey(baseAddress + i) && decRbpDone == false) { decRbpDone = true; x64Opcodes.decRbp.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 71: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.decRsp.ContainsKey(baseAddress + i) && decRspDone == false) { decRspDone = true; x64Opcodes.decRsp.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 72: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.decRsi.ContainsKey(baseAddress + i) && decRsiDone == false) { decRsiDone = true; x64Opcodes.decRsi.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 73: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.decRdi.ContainsKey(baseAddress + i) && decRdiDone == false) { decRdiDone = true; x64Opcodes.decRdi.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 74: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.decR8.ContainsKey(baseAddress + i) && decR8Done == false) { decR8Done = true; x64Opcodes.decR8.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 75: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.decR9.ContainsKey(baseAddress + i) && decR9Done == false) { decR9Done = true; x64Opcodes.decR9.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 76: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.decR10.ContainsKey(baseAddress + i) && decR10Done == false) { decR10Done = true; x64Opcodes.decR10.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 77: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.decR11.ContainsKey(baseAddress + i) && decR11Done == false) { decR11Done = true; x64Opcodes.decR11.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 78: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.decR12.ContainsKey(baseAddress + i) && decR12Done == false) { decR12Done = true; x64Opcodes.decR12.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 79: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.decR13.ContainsKey(baseAddress + i) && decR13Done == false) { decR13Done = true; x64Opcodes.decR13.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 80: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.decR14.ContainsKey(baseAddress + i) && decR14Done == false) { decR14Done = true; x64Opcodes.decR14.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 81: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.decR15.ContainsKey(baseAddress + i) && decR15Done == false) { decR15Done = true; x64Opcodes.decR15.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 32: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.xorRax.ContainsKey(baseAddress + i) && xorRaxDone == false) { xorRaxDone = true; x64Opcodes.xorRax.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 33: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.xorRbx.ContainsKey(baseAddress + i) && xorRbxDone == false) { xorRbxDone = true; x64Opcodes.xorRbx.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 34: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.xorRcx.ContainsKey(baseAddress + i) && xorRcxDone == false) { xorRcxDone = true; x64Opcodes.xorRcx.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 35: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.xorRdx.ContainsKey(baseAddress + i) && xorRdxDone == false) { xorRdxDone = true; x64Opcodes.xorRdx.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 36: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.xorRsi.ContainsKey(baseAddress + i) && xorRsiDone == false) { xorRsiDone = true; x64Opcodes.xorRsi.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 37: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.xorRdi.ContainsKey(baseAddress + i) && xorRdiDone == false) { xorRdiDone = true; x64Opcodes.xorRdi.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 38: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.xorR8.ContainsKey(baseAddress + i) && xorR8Done == false) { xorR8Done = true; x64Opcodes.xorR8.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 39: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.xorR9.ContainsKey(baseAddress + i) && xorR9Done == false) { xorR9Done = true; x64Opcodes.xorR9.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 40: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.xorR10.ContainsKey(baseAddress + i) && xorR10Done == false) { xorR10Done = true; x64Opcodes.xorR10.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 41: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.xorR11.ContainsKey(baseAddress + i) && xorR11Done == false) { xorR11Done = true; x64Opcodes.xorR11.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 42: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.xorR12.ContainsKey(baseAddress + i) && xorR12Done == false) { xorR12Done = true; x64Opcodes.xorR12.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 43: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.xorR13.ContainsKey(baseAddress + i) && xorR13Done == false) { xorR13Done = true; x64Opcodes.xorR13.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 44: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.xorR14.ContainsKey(baseAddress + i) && xorR14Done == false) { xorR14Done = true; x64Opcodes.xorR14.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; case 45: Array.Copy(bytes, i, opcodes, 0, bytes.Length - i); if (!x64Opcodes.xorR15.ContainsKey(baseAddress + i) && xorR15Done == false) { xorR15Done = true; x64Opcodes.xorR15.Add(baseAddress + i, OpcodeDisassembler.Disassemble(opcodes, MachineType.x64, info.ProcessCore).ReturnValue.Replace(Environment.NewLine, ", ")); } break; default: ret.Error = new ERCException("An error has occured in RopChainGenerator.ParseByteArrayForRopCodes whilst parsing triple length x64 instructions"); break; } } } } } return ret; } #endregion #region OptimiseLists private void OptimiseLists(ProcessInfo info) { usableX64Opcodes = new X64Lists(); var thisList = x64Opcodes.pushRax.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("push rax") || !thisList[i].Value.Contains("ret") || thisList[i].Value.Any(char.IsDigit)) { thisList.RemoveAt(i); } else { usableX64Opcodes.pushRax.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.pushRbx.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("push rbx") || !thisList[i].Value.Contains("ret") || thisList[i].Value.Any(char.IsDigit)) { thisList.RemoveAt(i); } else { usableX64Opcodes.pushRbx.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.pushRcx.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("push rcx") || !thisList[i].Value.Contains("ret") || thisList[i].Value.Any(char.IsDigit)) { thisList.RemoveAt(i); } else { usableX64Opcodes.pushRcx.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.pushRdx.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("push rdx") || !thisList[i].Value.Contains("ret") || thisList[i].Value.Any(char.IsDigit)) { thisList.RemoveAt(i); } else { usableX64Opcodes.pushRdx.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.pushRsp.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("push rsp") || !thisList[i].Value.Contains("ret") || thisList[i].Value.Any(char.IsDigit)) { thisList.RemoveAt(i); } else { usableX64Opcodes.pushRsp.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.pushRbp.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("push rbp") || !thisList[i].Value.Contains("ret") || thisList[i].Value.Any(char.IsDigit)) { thisList.RemoveAt(i); } else { usableX64Opcodes.pushRbp.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.pushRsi.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("push rsi") || !thisList[i].Value.Contains("ret") || thisList[i].Value.Any(char.IsDigit)) { thisList.RemoveAt(i); } else { usableX64Opcodes.pushRsi.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.pushRdi.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("push rdi") || !thisList[i].Value.Contains("ret") || thisList[i].Value.Any(char.IsDigit)) { thisList.RemoveAt(i); } else { usableX64Opcodes.pushRdi.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.pushR8.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("push r8") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX64Opcodes.pushR8.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.pushR9.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("push r9") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX64Opcodes.pushR9.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.pushR10.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("push r10") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX64Opcodes.pushR10.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.pushR11.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("push r11") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX64Opcodes.pushR11.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.pushR12.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("push r12") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX64Opcodes.pushR12.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.pushR13.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("push r13") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX64Opcodes.pushR13.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.pushR14.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("push r14") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX64Opcodes.pushR14.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.pushR15.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("push r15") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX64Opcodes.pushR15.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.jmpRsp.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("jmp rsp")) { thisList.RemoveAt(i); } else { usableX64Opcodes.jmpRsp.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.callRsp.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("call rsp")) { thisList.RemoveAt(i); } else { usableX64Opcodes.callRsp.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.xorRax.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("xor rax") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX64Opcodes.xorRax.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.xorRbx.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("xor rbx") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX64Opcodes.xorRbx.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.xorRcx.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("xor rcx") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX64Opcodes.xorRcx.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.xorRdx.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("xor rdx") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX64Opcodes.xorRdx.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.xorRsi.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("xor rsi") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX64Opcodes.xorRsi.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.xorRdi.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("xor rdi") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX64Opcodes.xorRdi.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.xorR8.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("xor r8") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX64Opcodes.xorR8.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.xorR9.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("xor r9") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX64Opcodes.xorR9.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.xorR10.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("xor r10") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX64Opcodes.xorR10.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.xorR11.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("xor r11") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX64Opcodes.xorR11.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.xorR12.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("xor r12") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX64Opcodes.xorR12.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.xorR13.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("xor r13") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX64Opcodes.xorR13.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.xorR14.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("xor r14") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX64Opcodes.xorR14.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.xorR15.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("xor r15") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX64Opcodes.xorR15.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.popRax.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("pop rax") || !thisList[i].Value.Contains("ret") || thisList[i].Value.Any(char.IsDigit)) { thisList.RemoveAt(i); } else { usableX64Opcodes.popRax.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.popRbx.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("pop rbx") || !thisList[i].Value.Contains("ret") || thisList[i].Value.Any(char.IsDigit)) { thisList.RemoveAt(i); } else { usableX64Opcodes.popRbx.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.popRcx.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("pop rcx") || !thisList[i].Value.Contains("ret") || thisList[i].Value.Any(char.IsDigit)) { thisList.RemoveAt(i); } else { usableX64Opcodes.popRcx.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.popRdx.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("pop rdx") || !thisList[i].Value.Contains("ret") || thisList[i].Value.Any(char.IsDigit)) { thisList.RemoveAt(i); } else { usableX64Opcodes.popRdx.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.popRsp.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("pop rsp") || !thisList[i].Value.Contains("ret") || thisList[i].Value.Any(char.IsDigit)) { thisList.RemoveAt(i); } else { usableX64Opcodes.popRsp.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.popRbp.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("pop rbp") || !thisList[i].Value.Contains("ret") || thisList[i].Value.Any(char.IsDigit)) { thisList.RemoveAt(i); } else { usableX64Opcodes.popRbp.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.popRsi.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("pop rsi") || !thisList[i].Value.Contains("ret") || thisList[i].Value.Any(char.IsDigit)) { thisList.RemoveAt(i); } else { usableX64Opcodes.popRsi.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.popRdi.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("pop rdi") || !thisList[i].Value.Contains("ret") || thisList[i].Value.Any(char.IsDigit)) { thisList.RemoveAt(i); } else { usableX64Opcodes.popRdi.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.popR8.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("pop r8") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX64Opcodes.popR8.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.popR9.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("pop r9") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX64Opcodes.popR9.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.popR10.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("pop r10") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX64Opcodes.popR10.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.popR11.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("pop r11") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX64Opcodes.popR11.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.popR12.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("pop r12") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX64Opcodes.popR12.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.popR13.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("pop r13") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX64Opcodes.popR13.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.popR14.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("pop r14") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX64Opcodes.popR14.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.popR15.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("pop r15") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX64Opcodes.popR15.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.incRax.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("inc rax") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX64Opcodes.incRax.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.incRbx.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("inc rbx") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX64Opcodes.incRbx.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.incRcx.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("inc rcx") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX64Opcodes.incRcx.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.incRdx.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("inc rdx") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX64Opcodes.incRdx.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.incRbp.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("inc rbp") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX64Opcodes.incRbp.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.incRsp.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("inc rsp") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX64Opcodes.incRsp.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.incRsi.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("inc rsi") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX64Opcodes.incRsi.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.incRdi.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("inc rdi") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX64Opcodes.incRdi.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.incR8.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("inc r8") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX64Opcodes.incR8.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.incR9.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("inc r9") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX64Opcodes.incR9.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.incR10.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("inc r10") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX64Opcodes.incR10.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.incR11.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("inc r11") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX64Opcodes.incR11.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.incR12.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("inc r12") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX64Opcodes.incR12.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.incR13.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("inc r13") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX64Opcodes.incR13.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.incR14.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("inc r14") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX64Opcodes.incR14.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.incR15.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("inc r15") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX64Opcodes.incR15.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.decRax.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("dec rax") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX64Opcodes.decRax.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.decRbx.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("dec rbx") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX64Opcodes.decRbx.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.decRcx.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("dec rcx") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX64Opcodes.decRcx.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.decRdx.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("dec rdx") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX64Opcodes.decRdx.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.decRbp.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("dec rbp") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX64Opcodes.decRbp.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.decRsp.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("dec rsp") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX64Opcodes.decRsp.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.decRsi.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("dec rsi") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX64Opcodes.decRsi.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.decRdi.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("dec rdi") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX64Opcodes.decRdi.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.decR8.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("dec r8") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX64Opcodes.decR8.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.decR9.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("dec r9") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX64Opcodes.decR9.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.decR10.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("dec r10") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX64Opcodes.decR10.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.decR11.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("dec r11") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX64Opcodes.decR11.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.decR12.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("dec r12") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX64Opcodes.decR12.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.decR13.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("dec r13") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX64Opcodes.decR13.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.decR14.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("dec r14") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX64Opcodes.decR14.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.decR15.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("dec r15") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX64Opcodes.decR15.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.add.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("add") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX64Opcodes.add.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.mov.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("mov") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX64Opcodes.mov.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.sub.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("sub") || !thisList[i].Value.Contains("ret")) { thisList.RemoveAt(i); } else { usableX64Opcodes.sub.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.jmpRax.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("jmp rax")) { thisList.RemoveAt(i); } else { usableX64Opcodes.jmpRax.Add(thisList[i].Key, thisList[i].Value); } } thisList = x64Opcodes.callRax.ToList(); thisList.Sort((x, y) => x.Value.Length.CompareTo(y.Value.Length)); for (int i = 0; i < thisList.Count; i++) { if (!thisList[i].Value.Contains("call rax")) { thisList.RemoveAt(i); } else { usableX64Opcodes.callRax.Add(thisList[i].Key, thisList[i].Value); } } } #endregion #region GenerateVirtualAllocChain64 private ErcResult>> GenerateVirtualAllocChain64(ProcessInfo info) { //////////////////////////////////////////////////////////////// // VirtualAlloc Template: // // RCX: 0x???????????????? -> Pointer // // RDX: 0x0000000000000500 -> dwSize // // R8 : 0x0000000000001000 -> flAllocationType // // R9 : 0x0000000000000040 -> flProtect // // // // + place a pointer to VirtualAlloc on stack // // + place ptr to "jmp rsp" on stack // //////////////////////////////////////////////////////////////// ErcResult>> VirtualAlloc = new ErcResult>>(info.ProcessCore); VirtualAlloc.ReturnValue = new List>(); Register64 regState64 = new Register64(); regState64 |= Register64.RSP; RegisterModifiers64 regModified64 = new RegisterModifiers64(); foreach (Register64 i in Enum.GetValues(typeof(Register64))) { SetRegisterModifier(regModified64.RSP, i, regModified64); SetRegisterModifier(i, regModified64.RSP, regModified64); } RegisterLists64 regLists64 = new RegisterLists64(); #region Populate RCX regLists64.rcxList = new List>(); for (int i = 0; i < usableX64Opcodes.popRcx.Count; i++) { if (!regState64.HasFlag(Register64.RCX)) { if (usableX64Opcodes.popRcx.ElementAt(i).Value.Length <= 14 && !usableX64Opcodes.popRcx.ElementAt(i).Value.Contains("invalid")) { for (int j = 0; j< usableX64Opcodes.pushRsp.Count; j++) { if (usableX64Opcodes.pushRsp.ElementAt(j).Value.Length <= 15 && !usableX64Opcodes.pushRsp.ElementAt(j).Value.Contains("invalid")) { regLists64.rcxList.Add(Tuple.Create(BitConverter.GetBytes((long)usableX64Opcodes.pushRsp.ElementAt(j).Key), usableX64Opcodes.pushRsp.ElementAt(j).Value)); regLists64.rcxList.Add(Tuple.Create(BitConverter.GetBytes((long)usableX64Opcodes.popRcx.ElementAt(i).Key), usableX64Opcodes.popRcx.ElementAt(i).Value)); regState64 |= Register64.RCX; i = usableX64Opcodes.popRcx.Count; j = usableX64Opcodes.pushRsp.Count; } } } } else { i = usableX64Opcodes.popRcx.Count; } } if (!regState64.HasFlag(Register64.RCX)) { var movInstruction = GetMovInstruction(Register64.RCX, Register64.RSP, regModified64); if (movInstruction != null) { regLists64.rcxList.Add(Tuple.Create(movInstruction.Item1, movInstruction.Item2)); SetRegisterModifier(Register64.RCX, Register64.RSP, regModified64); regState64 &= ~Register64.RSP; regState64 |= Register64.RCX; } } if (!regState64.HasFlag(Register64.RCX)) { regLists64.rcxList = null; regLists64.rcxList = new List>(); byte[] nullBytes = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; regLists64.rcxList.Add(Tuple.Create(nullBytes, "Unable to find appropriate instruction. RCX must be allocated manually")); regState64 |= Register64.RCX; } #endregion #region Populate RDX SetRegisterModifier(Register64.RDX, Register64.RCX, regModified64); regLists64.rdxList = null; regLists64.rdxList = new List>(); for (int i = 0; i < usableX64Opcodes.popRdx.Count; i++) { if (!regState64.HasFlag(Register64.RDX)) { if (usableX64Opcodes.popRdx.ElementAt(i).Value.Length <= 14 && !usableX64Opcodes.popRdx.ElementAt(i).Value.Contains("invalid")) { byte[] dwSize = { 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; regLists64.rdxList.Add(Tuple.Create(dwSize, "dwSize")); regLists64.rdxList.Add(Tuple.Create(BitConverter.GetBytes((long)usableX64Opcodes.popRdx.ElementAt(i).Key), usableX64Opcodes.popRdx.ElementAt(i).Value)); regState64 |= Register64.RDX; i = usableX64Opcodes.popRdx.Count; } } else { i = usableX64Opcodes.popRdx.Count; } } if (!regState64.HasFlag(Register64.RDX)) { var xorEbx = GetXorInstruction(Register64.RDX); if (xorEbx != null) { regLists64.rdxList.Add(Tuple.Create(xorEbx.Item1, xorEbx.Item2)); if (usableX64Opcodes.incRdx.Count > 0) { if (usableX64Opcodes.incRdx.ElementAt(0).Value.Length <= 14) { regLists64.rdxList.Add(Tuple.Create(BitConverter.GetBytes((long)usableX64Opcodes.incRdx.ElementAt(0).Key), usableX64Opcodes.incRdx.ElementAt(0).Value)); regState64 |= Register64.RDX; } } } } if (!regState64.HasFlag(Register64.RDX)) { var zeroEbx = ZeroRegister(Register64.RDX, regModified64); if (zeroEbx != null && usableX64Opcodes.incRdx.Count > 0 && usableX64Opcodes.incRdx.ElementAt(0).Value.Length <= 14) { for (int i = 0; i < zeroEbx.Count; i++) { regLists64.rdxList.Add(Tuple.Create(zeroEbx[i].Item1, zeroEbx[i].Item2)); } regLists64.rdxList.Add(Tuple.Create(BitConverter.GetBytes((long)usableX64Opcodes.incRdx.ElementAt(0).Key), usableX64Opcodes.incRdx.ElementAt(0).Value)); SetRegisterModifier(Register64.RDX, zeroEbx[0].Item3, regModified64); regState64 &= ~zeroEbx[0].Item3; regState64 |= Register64.RDX; } } if (!regState64.HasFlag(Register64.RDX)) { foreach (Register64 i in Enum.GetValues(typeof(Register64))) { var popInstruction = GetPopInstruction(Register64.RDX, i, regModified64); if (popInstruction != null) { for (int j = 0; j < usableX64Opcodes.add.Count; j++) { if (!regState64.HasFlag(Register64.RDX)) { var strings = usableX64Opcodes.add.ElementAt(j).Value.Split(','); if (strings[0].Contains(" rdx") && strings[1].Contains(i.ToString().ToLower())) { regLists64.rdxList.Add(Tuple.Create(popInstruction.Item1, popInstruction.Item2)); byte[] bytes = new byte[] { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; regLists64.rdxList.Add(Tuple.Create(bytes, "To be popped into " + i.ToString())); regLists64.rdxList.Add(Tuple.Create(BitConverter.GetBytes((long)usableX64Opcodes.add.ElementAt(j).Key), usableX64Opcodes.add.ElementAt(j).Value)); regLists64.rdxList.Add(Tuple.Create(popInstruction.Item1, popInstruction.Item2)); bytes = new byte[] { 0x01, 0x06, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }; regLists64.rdxList.Add(Tuple.Create(bytes, "To be popped into " + i.ToString())); regLists64.rdxList.Add(Tuple.Create(BitConverter.GetBytes((long)usableX64Opcodes.add.ElementAt(j).Key), usableX64Opcodes.add.ElementAt(j).Value)); SetRegisterModifier(Register64.RDX, i, regModified64); regState64 &= ~i; regState64 |= Register64.RDX; } } } } } } if (!regState64.HasFlag(Register64.RDX)) { regLists64.rdxList = null; regLists64.rdxList = new List>(); byte[] nullBytes = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; regLists64.rdxList.Add(Tuple.Create(nullBytes, "Unable to find appropriate instruction. EBX must be allocated manually")); regState64 |= Register64.RDX; } #endregion #region Populate R8 SetRegisterModifier(Register64.R8, Register64.RCX, regModified64); SetRegisterModifier(Register64.R8, Register64.RDX, regModified64); regLists64.r8List = null; regLists64.r8List = new List>(); var xorR8 = GetXorInstruction(Register64.R8); if (xorR8 != null) { foreach (Register64 i in Enum.GetValues(typeof(Register64))) { if (!regState64.HasFlag(Register64.R8)) { var popInstruction = GetPopInstruction(Register64.R8, i, regModified64); if (popInstruction != null) { var addInstruction = GetAddInstruction(Register64.R8, i); if (addInstruction != null) { byte[] add1 = new byte[] { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; byte[] add2 = new byte[] { 0x01, 0x11, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }; regLists64.r8List.Add(Tuple.Create(xorR8.Item1, xorR8.Item2)); regLists64.r8List.Add(Tuple.Create(add1, "To be placed into " + addInstruction.Item3.ToString())); regLists64.r8List.Add(Tuple.Create(addInstruction.Item1, addInstruction.Item2)); regLists64.r8List.Add(Tuple.Create(popInstruction.Item1, popInstruction.Item2)); regLists64.r8List.Add(Tuple.Create(add2, "To be placed into " + addInstruction.Item3.ToString() + " combined = 0x0000000000001000")); regLists64.r8List.Add(Tuple.Create(addInstruction.Item1, addInstruction.Item2)); regLists64.r8List.Add(Tuple.Create(popInstruction.Item1, popInstruction.Item2)); SetRegisterModifier(Register64.R8, i, regModified64); regState64 &= ~i; regState64 |= Register64.R8; } } } } } if (!regState64.HasFlag(Register64.R8)) { foreach (Register64 i in Enum.GetValues(typeof(Register64))) { if (!regState64.HasFlag(Register64.R8)) { var popInstruction = GetPopInstruction(Register64.R8, i, regModified64); if (popInstruction != null) { foreach (Register64 j in Enum.GetValues(typeof(Register64))) { if (!regState64.HasFlag(Register64.R8) && i != j) { var popInstruction2 = GetPopInstruction(Register64.R8, j, regModified64); if (popInstruction2 != null) { var addInstruction = GetAddInstruction(i, j); if (addInstruction != null) { var movInstruction = GetMovInstruction(Register64.R8, i, regModified64); if (movInstruction != null) { byte[] add1 = new byte[] { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; byte[] add2 = new byte[] { 0x01, 0x11, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }; regLists64.r8List.Add(Tuple.Create(add1, "To be placed into " + popInstruction.Item3.ToString())); regLists64.r8List.Add(Tuple.Create(popInstruction2.Item1, popInstruction2.Item2)); regLists64.r8List.Add(Tuple.Create(add2, "To be placed into " + addInstruction.Item3.ToString() + " combined = 0x0000000000000500")); regLists64.r8List.Add(Tuple.Create(addInstruction.Item1, addInstruction.Item2)); regLists64.r8List.Add(Tuple.Create(movInstruction.Item1, movInstruction.Item2)); regLists64.r8List.Add(Tuple.Create(popInstruction.Item1, popInstruction.Item2)); SetRegisterModifier(Register64.R8, i, regModified64); SetRegisterModifier(Register64.R8, j, regModified64); regState64 &= ~i; regState64 &= ~j; regState64 |= Register64.R8; } } } } } } } } } if (!regState64.HasFlag(Register64.R8)) { for (int i = 0; i < usableX64Opcodes.popR8.Count; i++) { if (!regState64.HasFlag(Register64.R8)) { if (usableX64Opcodes.popR8.ElementAt(i).Value.Length <= 14 && !usableX64Opcodes.popR8.ElementAt(i).Value.Contains("invalid")) { byte[] flAllocationType = { 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; regLists64.r8List.Add(Tuple.Create(flAllocationType, "flAllocationType")); regLists64.r8List.Add(Tuple.Create(BitConverter.GetBytes((long)usableX64Opcodes.popR8.ElementAt(i).Key), usableX64Opcodes.popR8.ElementAt(i).Value)); regState64 |= Register64.R8; i = usableX64Opcodes.popR8.Count; } } else { i = usableX64Opcodes.popR8.Count; } } } if (!regState64.HasFlag(Register64.R8)) { regLists64.r8List = null; regLists64.r8List = new List>(); byte[] nullBytes = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; regLists64.r8List.Add(Tuple.Create(nullBytes, "Unable to find appropriate instruction. R8 must be allocated manually")); regState64 |= Register64.R8; } #endregion #region Populate R9 SetRegisterModifier(Register64.R9, Register64.RCX, regModified64); SetRegisterModifier(Register64.R9, Register64.RDX, regModified64); SetRegisterModifier(Register64.R9, Register64.R8, regModified64); regLists64.r9List = null; regLists64.r9List = new List>(); var xorECX = GetXorInstruction(Register64.R9); if (xorECX != null) { foreach (Register64 i in Enum.GetValues(typeof(Register64))) { if (!regState64.HasFlag(Register64.R9)) { var popInstruction = GetPopInstruction(Register64.R9, i, regModified64); if (popInstruction != null) { var addInstruction = GetAddInstruction(Register64.R9, i); if (addInstruction != null) { byte[] add1 = new byte[] { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; byte[] add2 = new byte[] { 0x41, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }; regLists64.r9List.Add(Tuple.Create(xorECX.Item1, xorECX.Item2)); regLists64.r9List.Add(Tuple.Create(add1, "To be placed into " + addInstruction.Item3.ToString())); regLists64.r9List.Add(Tuple.Create(addInstruction.Item1, addInstruction.Item2)); regLists64.r9List.Add(Tuple.Create(popInstruction.Item1, popInstruction.Item2)); regLists64.r9List.Add(Tuple.Create(add2, "To be placed into " + addInstruction.Item3.ToString() + " combined = 0x00000040")); regLists64.r9List.Add(Tuple.Create(addInstruction.Item1, addInstruction.Item2)); regLists64.r9List.Add(Tuple.Create(popInstruction.Item1, popInstruction.Item2)); SetRegisterModifier(Register64.R9, i, regModified64); regState64 &= ~i; regState64 |= Register64.R9; } } } } } if (!regState64.HasFlag(Register64.R9)) { foreach (Register64 i in Enum.GetValues(typeof(Register64))) { if (!regState64.HasFlag(Register64.R9)) { var popInstruction = GetPopInstruction(Register64.R9, i, regModified64); if (popInstruction != null) { foreach (Register64 j in Enum.GetValues(typeof(Register64))) { if (!regState64.HasFlag(Register64.R9) && i != j) { var popInstruction2 = GetPopInstruction(Register64.R9, j, regModified64); if (popInstruction2 != null) { var addInstruction = GetAddInstruction(i, j); if (addInstruction != null) { var movInstruction = GetMovInstruction(Register64.R9, i, regModified64); if (movInstruction != null) { byte[] add1 = new byte[] { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; byte[] add2 = new byte[] { 0x41, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }; regLists64.r9List.Add(Tuple.Create(add1, "To be placed into " + popInstruction.Item3.ToString())); regLists64.r9List.Add(Tuple.Create(popInstruction2.Item1, popInstruction2.Item2)); regLists64.r9List.Add(Tuple.Create(add2, "To be placed into " + addInstruction.Item3.ToString() + " combined = 0x00000000000040")); regLists64.r9List.Add(Tuple.Create(addInstruction.Item1, addInstruction.Item2)); regLists64.r9List.Add(Tuple.Create(movInstruction.Item1, movInstruction.Item2)); regLists64.r9List.Add(Tuple.Create(popInstruction.Item1, popInstruction.Item2)); SetRegisterModifier(Register64.R9, i, regModified64); SetRegisterModifier(Register64.R9, j, regModified64); regState64 &= ~i; regState64 &= ~j; regState64 |= Register64.R9; } } } } } } } } } if (!regState64.HasFlag(Register64.R9)) { for (int i = 0; i < usableX64Opcodes.popR9.Count; i++) { if (!regState64.HasFlag(Register64.R9)) { if (usableX64Opcodes.popR9.ElementAt(i).Value.Length <= 14 && !usableX64Opcodes.popR9.ElementAt(i).Value.Contains("invalid")) { byte[] flProtect = { 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; regLists64.r9List.Add(Tuple.Create(flProtect, "flProtect")); regLists64.r9List.Add(Tuple.Create(BitConverter.GetBytes((long)usableX64Opcodes.popR9.ElementAt(i).Key), usableX64Opcodes.popR9.ElementAt(i).Value)); regState64 |= Register64.R9; i = usableX64Opcodes.popR9.Count; } } else { i = usableX64Opcodes.popR9.Count; } } } if (!regState64.HasFlag(Register64.R9)) { regLists64.r9List = null; regLists64.r9List = new List>(); byte[] nullBytes = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; regLists64.r9List.Add(Tuple.Create(nullBytes, "Unable to find appropriate instruction. R9 must be allocated manually")); regState64 |= Register64.R9; } #endregion VirtualAlloc.ReturnValue = BuildRopChain(RopMethod.VirtualAlloc, regLists64, regModified64); return VirtualAlloc; } #endregion #region GenerateHeapCreateChain private ErcResult>> GenerateHeapCreateChain64(ProcessInfo info) { //////////////////////////////////////////////////////////////// // HeapCreate Template: // // RCX: 0x0000000000040000 -> flOptions // // RDX: 0x0000000000000500 -> dwInitialSize // // R8 : 0x0000000000001000 -> dwMaximumSize // // // // + place a pointer to HeapCreate on stack // // + place ptr to "jmp rsp" on stack // //////////////////////////////////////////////////////////////// ErcResult>> HeapCreate = new ErcResult>>(info.ProcessCore); HeapCreate.ReturnValue = new List>(); Register64 regState64 = new Register64(); regState64 |= Register64.RSP; RegisterModifiers64 regModified64 = new RegisterModifiers64(); foreach (Register64 i in Enum.GetValues(typeof(Register64))) { SetRegisterModifier(regModified64.RSP, i, regModified64); SetRegisterModifier(i, regModified64.RSP, regModified64); } RegisterLists64 regLists64 = new RegisterLists64(); #region Populate RCX regLists64.rcxList = new List>(); for (int i = 0; i < usableX64Opcodes.popRcx.Count; i++) { if (!regState64.HasFlag(Register64.RCX)) { if (usableX64Opcodes.popRcx.ElementAt(i).Value.Length <= 14 && !usableX64Opcodes.popRcx.ElementAt(i).Value.Contains("invalid")) { byte[] flOptions = new byte[] { 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00 }; regLists64.rcxList.Add(Tuple.Create(flOptions,"flOptions")); regLists64.rcxList.Add(Tuple.Create(BitConverter.GetBytes((long)usableX64Opcodes.popRcx.ElementAt(i).Key), usableX64Opcodes.popRcx.ElementAt(i).Value)); regState64 |= Register64.RCX; i = usableX64Opcodes.popRcx.Count; } } else { i = usableX64Opcodes.popRcx.Count; } } if (!regState64.HasFlag(Register64.RCX)) { foreach (Register64 i in Enum.GetValues(typeof(Register64))) { var popInstruction = GetPopInstruction(Register64.RCX, i, regModified64); if (popInstruction != null) { for (int j = 0; j < usableX64Opcodes.add.Count; j++) { var strings = usableX64Opcodes.add.ElementAt(j).Value.Split(','); if (strings[0].Contains(" rcx") && strings[1].Contains(i.ToString().ToLower())) { byte[] bytes = new byte[] { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; regLists64.rcxList.Add(Tuple.Create(bytes, "To be popped into " + i.ToString())); regLists64.rcxList.Add(Tuple.Create(popInstruction.Item1, popInstruction.Item2)); regLists64.rcxList.Add(Tuple.Create(BitConverter.GetBytes((long)usableX64Opcodes.add.ElementAt(j).Key), usableX64Opcodes.add.ElementAt(j).Value)); bytes = new byte[] { 0x01, 0x06, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }; regLists64.rcxList.Add(Tuple.Create(bytes, "To be popped into " + i.ToString())); regLists64.rcxList.Add(Tuple.Create(popInstruction.Item1, popInstruction.Item2)); regLists64.rcxList.Add(Tuple.Create(BitConverter.GetBytes((long)usableX64Opcodes.add.ElementAt(j).Key), usableX64Opcodes.add.ElementAt(j).Value)); SetRegisterModifier(Register64.RCX, i, regModified64); regState64 &= ~i; regState64 |= Register64.RCX; j = usableX64Opcodes.add.Count + 1; } } } } } if (!regState64.HasFlag(Register64.RCX)) { regLists64.rcxList = null; regLists64.rcxList = new List>(); byte[] nullBytes = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; regLists64.rcxList.Add(Tuple.Create(nullBytes, "Unable to find appropriate instruction. RCX must be allocated manually")); regState64 |= Register64.RCX; } #endregion #region Populate RDX SetRegisterModifier(Register64.RDX, Register64.RCX, regModified64); regLists64.rdxList = null; regLists64.rdxList = new List>(); for (int i = 0; i < usableX64Opcodes.popRdx.Count; i++) { if (!regState64.HasFlag(Register64.RDX)) { if (usableX64Opcodes.popRdx.ElementAt(i).Value.Length <= 14 && !usableX64Opcodes.popRdx.ElementAt(i).Value.Contains("invalid")) { byte[] dwSize = { 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; regLists64.rdxList.Add(Tuple.Create(dwSize, "dwSize")); regLists64.rdxList.Add(Tuple.Create(BitConverter.GetBytes((long)usableX64Opcodes.popRdx.ElementAt(i).Key), usableX64Opcodes.popRdx.ElementAt(i).Value)); regState64 |= Register64.RDX; i = usableX64Opcodes.popRdx.Count; } } else { i = usableX64Opcodes.popRdx.Count; } } if (!regState64.HasFlag(Register64.RDX)) { var xorEbx = GetXorInstruction(Register64.RDX); if (xorEbx != null) { regLists64.rdxList.Add(Tuple.Create(xorEbx.Item1, xorEbx.Item2)); if (usableX64Opcodes.incRdx.Count > 0) { if (usableX64Opcodes.incRdx.ElementAt(0).Value.Length <= 14) { regLists64.rdxList.Add(Tuple.Create(BitConverter.GetBytes((long)usableX64Opcodes.incRdx.ElementAt(0).Key), usableX64Opcodes.incRdx.ElementAt(0).Value)); regState64 |= Register64.RDX; } } } } if (!regState64.HasFlag(Register64.RDX)) { var zeroEbx = ZeroRegister(Register64.RDX, regModified64); if (zeroEbx != null && usableX64Opcodes.incRdx.Count > 0 && usableX64Opcodes.incRdx.ElementAt(0).Value.Length <= 14) { for (int i = 0; i < zeroEbx.Count; i++) { regLists64.rdxList.Add(Tuple.Create(zeroEbx[i].Item1, zeroEbx[i].Item2)); } regLists64.rdxList.Add(Tuple.Create(BitConverter.GetBytes((long)usableX64Opcodes.incRdx.ElementAt(0).Key), usableX64Opcodes.incRdx.ElementAt(0).Value)); SetRegisterModifier(Register64.RDX, zeroEbx[0].Item3, regModified64); regState64 &= ~zeroEbx[0].Item3; regState64 |= Register64.RDX; } } if (!regState64.HasFlag(Register64.RDX)) { foreach (Register64 i in Enum.GetValues(typeof(Register64))) { var popInstruction = GetPopInstruction(Register64.RDX, i, regModified64); if (popInstruction != null) { for (int j = 0; j < usableX64Opcodes.add.Count; j++) { if (!regState64.HasFlag(Register64.RDX)) { var strings = usableX64Opcodes.add.ElementAt(j).Value.Split(','); if (strings[0].Contains(" rdx") && strings[1].Contains(i.ToString().ToLower())) { byte[] bytes = new byte[] { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; regLists64.rdxList.Add(Tuple.Create(bytes, "To be popped into " + i.ToString())); regLists64.rdxList.Add(Tuple.Create(popInstruction.Item1, popInstruction.Item2)); regLists64.rdxList.Add(Tuple.Create(BitConverter.GetBytes((long)usableX64Opcodes.add.ElementAt(j).Key), usableX64Opcodes.add.ElementAt(j).Value)); bytes = new byte[] { 0x01, 0x06, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }; regLists64.rdxList.Add(Tuple.Create(bytes, "To be popped into " + i.ToString())); regLists64.rdxList.Add(Tuple.Create(popInstruction.Item1, popInstruction.Item2)); regLists64.rdxList.Add(Tuple.Create(BitConverter.GetBytes((long)usableX64Opcodes.add.ElementAt(j).Key), usableX64Opcodes.add.ElementAt(j).Value)); SetRegisterModifier(Register64.RDX, i, regModified64); regState64 &= ~i; regState64 |= Register64.RDX; } } } } } } if (!regState64.HasFlag(Register64.RDX)) { regLists64.rdxList = null; regLists64.rdxList = new List>(); byte[] nullBytes = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; regLists64.rdxList.Add(Tuple.Create(nullBytes, "Unable to find appropriate instruction. EBX must be allocated manually")); regState64 |= Register64.RDX; } #endregion #region Populate R8 SetRegisterModifier(Register64.R8, Register64.RCX, regModified64); SetRegisterModifier(Register64.R8, Register64.RDX, regModified64); regLists64.r8List = null; regLists64.r8List = new List>(); var xorR8 = GetXorInstruction(Register64.R8); if (xorR8 != null) { foreach (Register64 i in Enum.GetValues(typeof(Register64))) { if (!regState64.HasFlag(Register64.R8)) { var popInstruction = GetPopInstruction(Register64.R8, i, regModified64); if (popInstruction != null) { var addInstruction = GetAddInstruction(Register64.R8, i); if (addInstruction != null) { byte[] add1 = new byte[] { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; byte[] add2 = new byte[] { 0x01, 0x11, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }; regLists64.r8List.Add(Tuple.Create(xorR8.Item1, xorR8.Item2)); regLists64.r8List.Add(Tuple.Create(add1, "To be placed into " + addInstruction.Item3.ToString())); regLists64.r8List.Add(Tuple.Create(addInstruction.Item1, addInstruction.Item2)); regLists64.r8List.Add(Tuple.Create(popInstruction.Item1, popInstruction.Item2)); regLists64.r8List.Add(Tuple.Create(add2, "To be placed into " + addInstruction.Item3.ToString() + " combined = 0x0000000000001000")); regLists64.r8List.Add(Tuple.Create(addInstruction.Item1, addInstruction.Item2)); regLists64.r8List.Add(Tuple.Create(popInstruction.Item1, popInstruction.Item2)); SetRegisterModifier(Register64.R8, i, regModified64); regState64 &= ~i; regState64 |= Register64.R8; } } } } } if (!regState64.HasFlag(Register64.R8)) { foreach (Register64 i in Enum.GetValues(typeof(Register64))) { if (!regState64.HasFlag(Register64.R8)) { var popInstruction = GetPopInstruction(Register64.R8, i, regModified64); if (popInstruction != null) { foreach (Register64 j in Enum.GetValues(typeof(Register64))) { if (!regState64.HasFlag(Register64.R8) && i != j) { var popInstruction2 = GetPopInstruction(Register64.R8, j, regModified64); if (popInstruction2 != null) { var addInstruction = GetAddInstruction(i, j); if (addInstruction != null) { var movInstruction = GetMovInstruction(Register64.R8, i, regModified64); if (movInstruction != null) { byte[] add1 = new byte[] { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; byte[] add2 = new byte[] { 0x01, 0x11, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }; regLists64.r8List.Add(Tuple.Create(add1, "To be placed into " + popInstruction.Item3.ToString())); regLists64.r8List.Add(Tuple.Create(popInstruction2.Item1, popInstruction2.Item2)); regLists64.r8List.Add(Tuple.Create(add2, "To be placed into " + addInstruction.Item3.ToString() + " combined = 0x0000000000000500")); regLists64.r8List.Add(Tuple.Create(addInstruction.Item1, addInstruction.Item2)); regLists64.r8List.Add(Tuple.Create(movInstruction.Item1, movInstruction.Item2)); regLists64.r8List.Add(Tuple.Create(popInstruction.Item1, popInstruction.Item2)); SetRegisterModifier(Register64.R8, i, regModified64); SetRegisterModifier(Register64.R8, j, regModified64); regState64 &= ~i; regState64 &= ~j; regState64 |= Register64.R8; } } } } } } } } } if (!regState64.HasFlag(Register64.R8)) { for (int i = 0; i < usableX64Opcodes.popR8.Count; i++) { if (!regState64.HasFlag(Register64.R8)) { if (usableX64Opcodes.popR8.ElementAt(i).Value.Length <= 14 && !usableX64Opcodes.popR8.ElementAt(i).Value.Contains("invalid")) { byte[] flAllocationType = { 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; regLists64.r8List.Add(Tuple.Create(flAllocationType, "flAllocationType")); regLists64.r8List.Add(Tuple.Create(BitConverter.GetBytes((long)usableX64Opcodes.popR8.ElementAt(i).Key), usableX64Opcodes.popR8.ElementAt(i).Value)); regState64 |= Register64.R8; i = usableX64Opcodes.popR8.Count; } } else { i = usableX64Opcodes.popR8.Count; } } } if (!regState64.HasFlag(Register64.R8)) { regLists64.r8List = null; regLists64.r8List = new List>(); byte[] nullBytes = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; regLists64.r8List.Add(Tuple.Create(nullBytes, "Unable to find appropriate instruction. R8 must be allocated manually")); regState64 |= Register64.R8; } #endregion HeapCreate.ReturnValue = BuildRopChain(RopMethod.HeapCreate, regLists64, regModified64); return HeapCreate; } #endregion #region GenerateVirtualProtectChain private ErcResult>> GenerateVirtualProtectChain64(ProcessInfo info) { //////////////////////////////////////////////////////////////// // VirtualProtect Template: // // RCX: 0x???????????????? -> Pointer // // RDX: 0x0000000000000500 -> dwSize // // R8 : 0x0000000000001000 -> flNewProtect // // R9 : 0x???????????????? -> lpflOldProtect // // // // + place a pointer to VirtualProtect on stack // // + place ptr to "jmp rsp" on stack // //////////////////////////////////////////////////////////////// ErcResult>> VirtualProtect = new ErcResult>>(info.ProcessCore); VirtualProtect.ReturnValue = new List>(); Register64 regState64 = new Register64(); regState64 |= Register64.RSP; RegisterModifiers64 regModified64 = new RegisterModifiers64(); foreach (Register64 i in Enum.GetValues(typeof(Register64))) { SetRegisterModifier(regModified64.RSP, i, regModified64); SetRegisterModifier(i, regModified64.RSP, regModified64); } RegisterLists64 regLists64 = new RegisterLists64(); #region Populate RCX regLists64.rcxList = new List>(); for (int i = 0; i < usableX64Opcodes.popRcx.Count; i++) { if (!regState64.HasFlag(Register64.RCX)) { if (usableX64Opcodes.popRcx.ElementAt(i).Value.Length <= 14 && !usableX64Opcodes.popRcx.ElementAt(i).Value.Contains("invalid")) { for (int j = 0; j < usableX64Opcodes.pushRsp.Count; j++) { if (usableX64Opcodes.pushRsp.ElementAt(j).Value.Length <= 15 && !usableX64Opcodes.pushRsp.ElementAt(j).Value.Contains("invalid")) { regLists64.rcxList.Add(Tuple.Create(BitConverter.GetBytes((long)usableX64Opcodes.pushRsp.ElementAt(j).Key), usableX64Opcodes.pushRsp.ElementAt(j).Value)); regLists64.rcxList.Add(Tuple.Create(BitConverter.GetBytes((long)usableX64Opcodes.popRcx.ElementAt(i).Key), usableX64Opcodes.popRcx.ElementAt(i).Value)); regState64 |= Register64.RCX; i = usableX64Opcodes.popRcx.Count; j = usableX64Opcodes.pushRsp.Count; } } } } else { i = usableX64Opcodes.popRcx.Count; } } if (!regState64.HasFlag(Register64.RCX)) { var movInstruction = GetMovInstruction(Register64.RCX, Register64.RSP, regModified64); if (movInstruction != null) { regLists64.rcxList.Add(Tuple.Create(movInstruction.Item1, movInstruction.Item2)); SetRegisterModifier(Register64.RCX, Register64.RSP, regModified64); regState64 &= ~Register64.RSP; regState64 |= Register64.RCX; } } if (!regState64.HasFlag(Register64.RCX)) { regLists64.rcxList = null; regLists64.rcxList = new List>(); byte[] nullBytes = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; regLists64.rcxList.Add(Tuple.Create(nullBytes, "Unable to find appropriate instruction. RCX must be allocated manually")); regState64 |= Register64.RCX; } #endregion #region Populate RDX SetRegisterModifier(Register64.RDX, Register64.RCX, regModified64); regLists64.rdxList = null; regLists64.rdxList = new List>(); for (int i = 0; i < usableX64Opcodes.popRdx.Count; i++) { if (!regState64.HasFlag(Register64.RDX)) { if (usableX64Opcodes.popRdx.ElementAt(i).Value.Length <= 14 && !usableX64Opcodes.popRdx.ElementAt(i).Value.Contains("invalid")) { byte[] dwSize = { 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; regLists64.rdxList.Add(Tuple.Create(dwSize, "dwSize")); regLists64.rdxList.Add(Tuple.Create(BitConverter.GetBytes((long)usableX64Opcodes.popRdx.ElementAt(i).Key), usableX64Opcodes.popRdx.ElementAt(i).Value)); regState64 |= Register64.RDX; i = usableX64Opcodes.popRdx.Count; } } else { i = usableX64Opcodes.popRdx.Count; } } if (!regState64.HasFlag(Register64.RDX)) { var xorEbx = GetXorInstruction(Register64.RDX); if (xorEbx != null) { regLists64.rdxList.Add(Tuple.Create(xorEbx.Item1, xorEbx.Item2)); if (usableX64Opcodes.incRdx.Count > 0) { if (usableX64Opcodes.incRdx.ElementAt(0).Value.Length <= 14) { regLists64.rdxList.Add(Tuple.Create(BitConverter.GetBytes((long)usableX64Opcodes.incRdx.ElementAt(0).Key), usableX64Opcodes.incRdx.ElementAt(0).Value)); regState64 |= Register64.RDX; } } } } if (!regState64.HasFlag(Register64.RDX)) { var zeroEbx = ZeroRegister(Register64.RDX, regModified64); if (zeroEbx != null && usableX64Opcodes.incRdx.Count > 0 && usableX64Opcodes.incRdx.ElementAt(0).Value.Length <= 14) { for (int i = 0; i < zeroEbx.Count; i++) { regLists64.rdxList.Add(Tuple.Create(zeroEbx[i].Item1, zeroEbx[i].Item2)); } regLists64.rdxList.Add(Tuple.Create(BitConverter.GetBytes((long)usableX64Opcodes.incRdx.ElementAt(0).Key), usableX64Opcodes.incRdx.ElementAt(0).Value)); SetRegisterModifier(Register64.RDX, zeroEbx[0].Item3, regModified64); regState64 &= ~zeroEbx[0].Item3; regState64 |= Register64.RDX; } } if (!regState64.HasFlag(Register64.RDX)) { foreach (Register64 i in Enum.GetValues(typeof(Register64))) { var popInstruction = GetPopInstruction(Register64.RDX, i, regModified64); if (popInstruction != null) { for (int j = 0; j < usableX64Opcodes.add.Count; j++) { if (!regState64.HasFlag(Register64.RDX)) { var strings = usableX64Opcodes.add.ElementAt(j).Value.Split(','); if (strings[0].Contains(" rdx") && strings[1].Contains(i.ToString().ToLower())) { regLists64.rdxList.Add(Tuple.Create(popInstruction.Item1, popInstruction.Item2)); byte[] bytes = new byte[] { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; regLists64.rdxList.Add(Tuple.Create(bytes, "To be popped into " + i.ToString())); regLists64.rdxList.Add(Tuple.Create(BitConverter.GetBytes((long)usableX64Opcodes.add.ElementAt(j).Key), usableX64Opcodes.add.ElementAt(j).Value)); regLists64.rdxList.Add(Tuple.Create(popInstruction.Item1, popInstruction.Item2)); bytes = new byte[] { 0x01, 0x06, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }; regLists64.rdxList.Add(Tuple.Create(bytes, "To be popped into " + i.ToString())); regLists64.rdxList.Add(Tuple.Create(BitConverter.GetBytes((long)usableX64Opcodes.add.ElementAt(j).Key), usableX64Opcodes.add.ElementAt(j).Value)); SetRegisterModifier(Register64.RDX, i, regModified64); regState64 &= ~i; regState64 |= Register64.RDX; } } } } } } if (!regState64.HasFlag(Register64.RDX)) { regLists64.rdxList = null; regLists64.rdxList = new List>(); byte[] nullBytes = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; regLists64.rdxList.Add(Tuple.Create(nullBytes, "Unable to find appropriate instruction. EBX must be allocated manually")); regState64 |= Register64.RDX; } #endregion #region Populate R8 SetRegisterModifier(Register64.R8, Register64.RCX, regModified64); SetRegisterModifier(Register64.R8, Register64.RDX, regModified64); regLists64.r8List = null; regLists64.r8List = new List>(); var xorR8 = GetXorInstruction(Register64.R8); if (xorR8 != null) { foreach (Register64 i in Enum.GetValues(typeof(Register64))) { if (!regState64.HasFlag(Register64.R8)) { var popInstruction = GetPopInstruction(Register64.R8, i, regModified64); if (popInstruction != null) { var addInstruction = GetAddInstruction(Register64.R8, i); if (addInstruction != null) { byte[] add1 = new byte[] { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; byte[] add2 = new byte[] { 0x01, 0x11, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }; regLists64.r8List.Add(Tuple.Create(xorR8.Item1, xorR8.Item2)); regLists64.r8List.Add(Tuple.Create(add1, "To be placed into " + addInstruction.Item3.ToString())); regLists64.r8List.Add(Tuple.Create(addInstruction.Item1, addInstruction.Item2)); regLists64.r8List.Add(Tuple.Create(popInstruction.Item1, popInstruction.Item2)); regLists64.r8List.Add(Tuple.Create(add2, "To be placed into " + addInstruction.Item3.ToString() + " combined = 0x0000000000001000")); regLists64.r8List.Add(Tuple.Create(addInstruction.Item1, addInstruction.Item2)); regLists64.r8List.Add(Tuple.Create(popInstruction.Item1, popInstruction.Item2)); SetRegisterModifier(Register64.R8, i, regModified64); regState64 &= ~i; regState64 |= Register64.R8; } } } } } if (!regState64.HasFlag(Register64.R8)) { foreach (Register64 i in Enum.GetValues(typeof(Register64))) { if (!regState64.HasFlag(Register64.R8)) { var popInstruction = GetPopInstruction(Register64.R8, i, regModified64); if (popInstruction != null) { foreach (Register64 j in Enum.GetValues(typeof(Register64))) { if (!regState64.HasFlag(Register64.R8) && i != j) { var popInstruction2 = GetPopInstruction(Register64.R8, j, regModified64); if (popInstruction2 != null) { var addInstruction = GetAddInstruction(i, j); if (addInstruction != null) { var movInstruction = GetMovInstruction(Register64.R8, i, regModified64); if (movInstruction != null) { byte[] add1 = new byte[] { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; byte[] add2 = new byte[] { 0x01, 0x11, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }; regLists64.r8List.Add(Tuple.Create(add1, "To be placed into " + popInstruction.Item3.ToString())); regLists64.r8List.Add(Tuple.Create(popInstruction2.Item1, popInstruction2.Item2)); regLists64.r8List.Add(Tuple.Create(add2, "To be placed into " + addInstruction.Item3.ToString() + " combined = 0x0000000000001000")); regLists64.r8List.Add(Tuple.Create(addInstruction.Item1, addInstruction.Item2)); regLists64.r8List.Add(Tuple.Create(movInstruction.Item1, movInstruction.Item2)); regLists64.r8List.Add(Tuple.Create(popInstruction.Item1, popInstruction.Item2)); SetRegisterModifier(Register64.R8, i, regModified64); SetRegisterModifier(Register64.R8, j, regModified64); regState64 &= ~i; regState64 &= ~j; regState64 |= Register64.R8; } } } } } } } } } if (!regState64.HasFlag(Register64.R8)) { for (int i = 0; i < usableX64Opcodes.popR8.Count; i++) { if (!regState64.HasFlag(Register64.R8)) { if (usableX64Opcodes.popR8.ElementAt(i).Value.Length <= 14 && !usableX64Opcodes.popR8.ElementAt(i).Value.Contains("invalid")) { byte[] flAllocationType = { 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; regLists64.r8List.Add(Tuple.Create(flAllocationType, "flAllocationType")); regLists64.r8List.Add(Tuple.Create(BitConverter.GetBytes((long)usableX64Opcodes.popR8.ElementAt(i).Key), usableX64Opcodes.popR8.ElementAt(i).Value)); regState64 |= Register64.R8; i = usableX64Opcodes.popR8.Count; } } else { i = usableX64Opcodes.popR8.Count; } } } if (!regState64.HasFlag(Register64.R8)) { regLists64.r8List = null; regLists64.r8List = new List>(); byte[] nullBytes = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; regLists64.r8List.Add(Tuple.Create(nullBytes, "Unable to find appropriate instruction. R8 must be allocated manually")); regState64 |= Register64.R8; } #endregion #region Populate R9 regLists64.r9List = new List>(); for (int i = 0; i < usableX64Opcodes.popR9.Count; i++) { if (!regState64.HasFlag(Register64.R9)) { if (usableX64Opcodes.popR9.ElementAt(i).Value.Length <= 14 && !usableX64Opcodes.popR9.ElementAt(i).Value.Contains("invalid")) { for (int j = 0; j < usableX64Opcodes.pushRsp.Count; j++) { if (usableX64Opcodes.pushRsp.ElementAt(j).Value.Length <= 15 && !usableX64Opcodes.pushRsp.ElementAt(j).Value.Contains("invalid")) { regLists64.r9List.Add(Tuple.Create(BitConverter.GetBytes((long)usableX64Opcodes.pushRsp.ElementAt(j).Key), usableX64Opcodes.pushRsp.ElementAt(j).Value)); regLists64.r9List.Add(Tuple.Create(BitConverter.GetBytes((long)usableX64Opcodes.popR9.ElementAt(i).Key), usableX64Opcodes.popR9.ElementAt(i).Value)); regState64 |= Register64.R9; i = usableX64Opcodes.popR9.Count; j = usableX64Opcodes.pushRsp.Count; } } } } else { i = usableX64Opcodes.popR9.Count; } } if (!regState64.HasFlag(Register64.R9)) { var movInstruction = GetMovInstruction(Register64.R9, Register64.RSP, regModified64); if (movInstruction != null) { regLists64.r9List.Add(Tuple.Create(movInstruction.Item1, movInstruction.Item2)); SetRegisterModifier(Register64.R9, Register64.RSP, regModified64); regState64 &= ~Register64.RSP; regState64 |= Register64.R9; } } if (!regState64.HasFlag(Register64.R9)) { regLists64.r9List = null; regLists64.r9List = new List>(); byte[] nullBytes = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; regLists64.r9List.Add(Tuple.Create(nullBytes, "Unable to find appropriate instruction. R9 must be allocated manually")); regState64 |= Register64.R9; } #endregion VirtualProtect.ReturnValue = BuildRopChain(RopMethod.VirtualProtect, regLists64, regModified64); return VirtualProtect; } #endregion #region BuildRopChain private List> BuildRopChain(RopMethod method, RegisterLists64 regLists64, RegisterModifiers64 regModified64) { List> ret = new List>(); List order = new List(); for (int i = 0; i < regLists64.rcxList.Count; i++) { ret.Add(regLists64.rcxList[i]); } for (int i = 0; i < regLists64.rdxList.Count; i++) { ret.Add(regLists64.rdxList[i]); } for (int i = 0; i < regLists64.r8List.Count; i++) { ret.Add(regLists64.r8List[i]); } for (int i = 0; i < regLists64.r9List.Count; i++) { ret.Add(regLists64.r9List[i]); } switch (method) { case RopMethod.VirtualAlloc: ret.Add(Tuple.Create(BitConverter.GetBytes((long)ApiAddresses["VirtualAlloc"]), "Pointer to VirtualAlloc.")); ret.Add(Tuple.Create(BitConverter.GetBytes((long)usableX64Opcodes.jmpRsp.ElementAt(0).Key), usableX64Opcodes.jmpRsp.ElementAt(0).Value)); break; case RopMethod.HeapCreate: ret.Add(Tuple.Create(BitConverter.GetBytes((long)ApiAddresses["HeapCreate"]), "Pointer to HeapCreate.")); ret.Add(Tuple.Create(BitConverter.GetBytes((long)usableX64Opcodes.jmpRax.ElementAt(0).Key), usableX64Opcodes.jmpRax.ElementAt(0).Value)); break; case RopMethod.VirtualProtect: ret.Add(Tuple.Create(BitConverter.GetBytes((long)ApiAddresses["VirtualProtect"]), "Pointer to VirtualProtect.")); ret.Add(Tuple.Create(BitConverter.GetBytes((long)usableX64Opcodes.jmpRsp.ElementAt(0).Key), usableX64Opcodes.jmpRsp.ElementAt(0).Value)); break; default: break; } return ret; } #endregion #region CalculateAddInstructions64 private byte[] CalculateAddInstructions64(int size) { byte[] sizeBytes = BitConverter.GetBytes(size); byte[] modifiedBytes = new byte[8]; Array.Copy(sizeBytes, 0, modifiedBytes, modifiedBytes.Length - sizeBytes.Length, sizeBytes.Length); for (int i = 0; i < modifiedBytes.Length; i++) { modifiedBytes[i] += 0x01; } return modifiedBytes; } #endregion region #region ZeroRegister /// /// Checks for a combination of instructions that can be used to zero out a register, this can be a xor instruction on itself or a xor instruction elsewhere /// followed by a move to the selected register. This function should be extended with further methods for zeroing a register at a later date. /// /// The Register64 value for the register to be zeroed. /// The RegisterModifiers64 object. /// A dictionary(byte[], string) containing pointers to the instructions and the associated mnemonics private List> ZeroRegister(Register64 modifyingReg, RegisterModifiers64 regModified64) { List> instructions = new List>(); var xor = GetXorInstruction(modifyingReg); if (xor != null) { instructions.Add(xor); return instructions; } for (int i = 0; i < usableX64Opcodes.mov.Count; i++) { string[] gadgetElements = usableX64Opcodes.mov.ElementAt(i).Value.Split(','); if (gadgetElements[0].Contains(modifyingReg.ToString().ToLower())) { var reg = registerIdentifier64(gadgetElements[1]); if (reg != Register64.NONE && !GetRegisterModified(modifyingReg, reg, regModified64)) { var xorReg = GetXorInstruction(reg); if (xorReg != null && !GetRegisterModified(modifyingReg, reg, regModified64)) { instructions.Add(xorReg); instructions.Add(Tuple.Create(BitConverter.GetBytes((long)usableX64Opcodes.mov.ElementAt(i).Key).Reverse().ToArray(), usableX64Opcodes.mov.ElementAt(i).Value, reg)); return instructions; } } } } return null; } #endregion #region SetRegisterModifier 64 bit /// /// Sets the flag of a Register64 enum in a RegisterModifiers64 class. This flag is used to identify whether setting the value of one /// register involved editing another register. For example if setting EAX involved modifying RBX then RegisterModifiers32.RAX will have the RBX flag set. Any /// register should not be able to modify the value of any other register twice. /// /// The purpose of this is to stop an infitinte loop where each register modifies the other in order to achieve the correct value. /// /// The Register64 which is being modified /// The Register64 which is doing the modification /// The RegisterModifiers64 object. private void SetRegisterModifier(Register64 modifyingReg, Register64 modifiedReg, RegisterModifiers64 regModified64) { switch (modifyingReg) { case Register64.RAX: regModified64.RAX |= modifiedReg; return; case Register64.RBX: regModified64.RBX |= modifiedReg; return; case Register64.RCX: regModified64.RCX |= modifiedReg; return; case Register64.RDX: regModified64.RDX |= modifiedReg; return; case Register64.RBP: regModified64.RBP |= modifiedReg; return; case Register64.RSP: regModified64.RSP |= modifiedReg; return; case Register64.RSI: regModified64.RSI |= modifiedReg; return; case Register64.RDI: regModified64.RDI |= modifiedReg; return; case Register64.R8: regModified64.R8 |= modifiedReg; return; case Register64.R9: regModified64.R9 |= modifiedReg; return; case Register64.R10: regModified64.R10 |= modifiedReg; return; case Register64.R11: regModified64.R11 |= modifiedReg; return; case Register64.R12: regModified64.R12 |= modifiedReg; return; case Register64.R13: regModified64.R13 |= modifiedReg; return; case Register64.R14: regModified64.R14 |= modifiedReg; return; case Register64.R15: regModified64.R15 |= modifiedReg; return; } } #endregion #region GetRegisterModifier 64 bit private bool GetRegisterModified(Register64 modifyingReg, Register64 modifiedReg, RegisterModifiers64 regModified64) { Register64 thisReg; bool modified = false; switch (modifyingReg) { case Register64.RAX: thisReg = regModified64.RAX; break; case Register64.RBX: thisReg = regModified64.RBX; break; case Register64.RCX: thisReg = regModified64.RCX; break; case Register64.RDX: thisReg = regModified64.RDX; break; case Register64.RBP: thisReg = regModified64.RBP; break; case Register64.RSP: thisReg = regModified64.RSP; break; case Register64.RSI: thisReg = regModified64.RSI; break; case Register64.RDI: thisReg = regModified64.RDI; break; case Register64.R8: thisReg = regModified64.R9; break; case Register64.R9: thisReg = regModified64.R9; break; case Register64.R10: thisReg = regModified64.R10; break; case Register64.R11: thisReg = regModified64.R11; break; case Register64.R12: thisReg = regModified64.R12; break; case Register64.R13: thisReg = regModified64.R13; break; case Register64.R14: thisReg = regModified64.R14; break; case Register64.R15: thisReg = regModified64.R15; break; default: return true; } if (thisReg.HasFlag(modifiedReg)) { modified = true; } return modified; } #endregion #region GetPopInstruction 64 bit private Tuple GetPopInstruction(Register64 destReg, Register64 srcReg, RegisterModifiers64 regModified64) { switch (srcReg) { case Register64.RAX: for (int i = 0; i < usableX64Opcodes.popRax.Count; i++) { if (usableX64Opcodes.popRax.ElementAt(i).Value.Length == 14 && !GetRegisterModified(destReg, Register64.RAX, regModified64)) { return Tuple.Create(BitConverter.GetBytes((long)usableX64Opcodes.popRax.ElementAt(i).Key).Reverse().ToArray(), usableX64Opcodes.popRax.ElementAt(i).Value, Register64.RAX); } } break; case Register64.RBX: for (int i = 0; i < usableX64Opcodes.popRbx.Count; i++) { if (usableX64Opcodes.popRbx.ElementAt(i).Value.Length == 14 && !GetRegisterModified(destReg, Register64.RBX, regModified64)) { return Tuple.Create(BitConverter.GetBytes((long)usableX64Opcodes.popRbx.ElementAt(i).Key).Reverse().ToArray(), usableX64Opcodes.popRbx.ElementAt(i).Value, Register64.RBX); } } break; case Register64.RCX: for (int i = 0; i < usableX64Opcodes.popRcx.Count; i++) { if (usableX64Opcodes.popRcx.ElementAt(i).Value.Length == 14 && !GetRegisterModified(destReg, Register64.RCX, regModified64)) { return Tuple.Create(BitConverter.GetBytes((long)usableX64Opcodes.popRcx.ElementAt(i).Key).Reverse().ToArray(), usableX64Opcodes.popRcx.ElementAt(i).Value, Register64.RCX); } } break; case Register64.RDX: for (int i = 0; i < usableX64Opcodes.popRdx.Count; i++) { if (usableX64Opcodes.popRdx.ElementAt(i).Value.Length == 14 && !GetRegisterModified(destReg, Register64.RDX, regModified64)) { return Tuple.Create(BitConverter.GetBytes((long)usableX64Opcodes.popRdx.ElementAt(i).Key).Reverse().ToArray(), usableX64Opcodes.popRdx.ElementAt(i).Value, Register64.RDX); } } break; case Register64.RBP: for (int i = 0; i < usableX64Opcodes.popRbp.Count; i++) { if (usableX64Opcodes.popRbp.ElementAt(i).Value.Length == 14 && !GetRegisterModified(destReg, Register64.RBP, regModified64)) { return Tuple.Create(BitConverter.GetBytes((long)usableX64Opcodes.popRbp.ElementAt(i).Key).Reverse().ToArray(), usableX64Opcodes.popRbp.ElementAt(i).Value, Register64.RBP); } } break; case Register64.RSP: for (int i = 0; i < usableX64Opcodes.popRsp.Count; i++) { if (usableX64Opcodes.popRsp.ElementAt(i).Value.Length == 14 && !GetRegisterModified(destReg, Register64.RSP, regModified64)) { return Tuple.Create(BitConverter.GetBytes((long)usableX64Opcodes.popRsp.ElementAt(i).Key).Reverse().ToArray(), usableX64Opcodes.popRsp.ElementAt(i).Value, Register64.RSP); } } break; case Register64.RSI: for (int i = 0; i < usableX64Opcodes.popRsi.Count; i++) { if (usableX64Opcodes.popRsi.ElementAt(i).Value.Length == 14 && !GetRegisterModified(destReg, Register64.RSI, regModified64)) { return Tuple.Create(BitConverter.GetBytes((long)usableX64Opcodes.popRsi.ElementAt(i).Key).Reverse().ToArray(), usableX64Opcodes.popRsi.ElementAt(i).Value, Register64.RSI); } } break; case Register64.RDI: for (int i = 0; i < usableX64Opcodes.popRdi.Count; i++) { if (usableX64Opcodes.popRdi.ElementAt(i).Value.Length == 14 && !GetRegisterModified(destReg, Register64.RDI, regModified64)) { return Tuple.Create(BitConverter.GetBytes((long)usableX64Opcodes.popRdi.ElementAt(i).Key).Reverse().ToArray(), usableX64Opcodes.popRdi.ElementAt(i).Value, Register64.RDI); } } break; case Register64.R8: for (int i = 0; i < usableX64Opcodes.popR8.Count; i++) { if (usableX64Opcodes.popR8.ElementAt(i).Value.Length == 14 && !GetRegisterModified(destReg, Register64.R8, regModified64)) { return Tuple.Create(BitConverter.GetBytes((long)usableX64Opcodes.popR8.ElementAt(i).Key).Reverse().ToArray(), usableX64Opcodes.popR8.ElementAt(i).Value, Register64.R8); } } break; case Register64.R9: for (int i = 0; i < usableX64Opcodes.popR9.Count; i++) { if (usableX64Opcodes.popR9.ElementAt(i).Value.Length == 14 && !GetRegisterModified(destReg, Register64.R9, regModified64)) { return Tuple.Create(BitConverter.GetBytes((long)usableX64Opcodes.popR9.ElementAt(i).Key).Reverse().ToArray(), usableX64Opcodes.popR9.ElementAt(i).Value, Register64.R9); } } break; case Register64.R10: for (int i = 0; i < usableX64Opcodes.popR10.Count; i++) { if (usableX64Opcodes.popR10.ElementAt(i).Value.Length == 14 && !GetRegisterModified(destReg, Register64.R10, regModified64)) { return Tuple.Create(BitConverter.GetBytes((long)usableX64Opcodes.popR10.ElementAt(i).Key).Reverse().ToArray(), usableX64Opcodes.popR10.ElementAt(i).Value, Register64.R10); } } break; case Register64.R11: for (int i = 0; i < usableX64Opcodes.popR11.Count; i++) { if (usableX64Opcodes.popR11.ElementAt(i).Value.Length == 14 && !GetRegisterModified(destReg, Register64.R11, regModified64)) { return Tuple.Create(BitConverter.GetBytes((long)usableX64Opcodes.popR11.ElementAt(i).Key).Reverse().ToArray(), usableX64Opcodes.popR11.ElementAt(i).Value, Register64.R11); } } break; case Register64.R12: for (int i = 0; i < usableX64Opcodes.popR12.Count; i++) { if (usableX64Opcodes.popR12.ElementAt(i).Value.Length == 14 && !GetRegisterModified(destReg, Register64.R12, regModified64)) { return Tuple.Create(BitConverter.GetBytes((long)usableX64Opcodes.popR12.ElementAt(i).Key).Reverse().ToArray(), usableX64Opcodes.popR12.ElementAt(i).Value, Register64.R12); } } break; case Register64.R13: for (int i = 0; i < usableX64Opcodes.popR13.Count; i++) { if (usableX64Opcodes.popR13.ElementAt(i).Value.Length == 14 && !GetRegisterModified(destReg, Register64.R13, regModified64)) { return Tuple.Create(BitConverter.GetBytes((long)usableX64Opcodes.popR13.ElementAt(i).Key).Reverse().ToArray(), usableX64Opcodes.popR13.ElementAt(i).Value, Register64.R13); } } break; case Register64.R14: for (int i = 0; i < usableX64Opcodes.popR14.Count; i++) { if (usableX64Opcodes.popR14.ElementAt(i).Value.Length == 14 && !GetRegisterModified(destReg, Register64.R14, regModified64)) { return Tuple.Create(BitConverter.GetBytes((long)usableX64Opcodes.popR14.ElementAt(i).Key).Reverse().ToArray(), usableX64Opcodes.popR14.ElementAt(i).Value, Register64.R14); } } break; case Register64.R15: for (int i = 0; i < usableX64Opcodes.popR15.Count; i++) { if (usableX64Opcodes.popR15.ElementAt(i).Value.Length == 15 && !GetRegisterModified(destReg, Register64.R15, regModified64)) { return Tuple.Create(BitConverter.GetBytes((long)usableX64Opcodes.popR15.ElementAt(i).Key).Reverse().ToArray(), usableX64Opcodes.popR15.ElementAt(i).Value, Register64.R15); } } break; default: return null; } return null; } #endregion #region getXorInstruction 64 bit private Tuple GetXorInstruction(Register64 reg) { switch (reg) { case Register64.RAX: if (usableX64Opcodes.xorRax.Count > 0 && usableX64Opcodes.xorRax.ElementAt(0).Value.Length <= 19) { byte[] gadget1 = BitConverter.GetBytes((long)usableX64Opcodes.xorRax.ElementAt(0).Key).Reverse().ToArray(); return Tuple.Create(gadget1, usableX64Opcodes.xorRax.ElementAt(0).Value, Register64.RAX); } break; case Register64.RBX: if (usableX64Opcodes.xorRbx.Count > 0 && usableX64Opcodes.xorRbx.ElementAt(0).Value.Length <= 19) { byte[] gadget1 = BitConverter.GetBytes((long)usableX64Opcodes.xorRbx.ElementAt(0).Key).Reverse().ToArray(); return Tuple.Create(gadget1, usableX64Opcodes.xorRbx.ElementAt(0).Value, Register64.RBX); } break; case Register64.RCX: if (usableX64Opcodes.xorRcx.Count > 0 && usableX64Opcodes.xorRcx.ElementAt(0).Value.Length <= 19) { byte[] gadget1 = BitConverter.GetBytes((long)usableX64Opcodes.xorRcx.ElementAt(0).Key).Reverse().ToArray(); return Tuple.Create(gadget1, usableX64Opcodes.xorRcx.ElementAt(0).Value, Register64.RCX); } break; case Register64.RDX: if (usableX64Opcodes.xorRdx.Count > 0 && usableX64Opcodes.xorRdx.ElementAt(0).Value.Length <= 19) { byte[] gadget1 = BitConverter.GetBytes((long)usableX64Opcodes.xorRdx.ElementAt(0).Key).Reverse().ToArray(); return Tuple.Create(gadget1, usableX64Opcodes.xorRdx.ElementAt(0).Value, Register64.RDX); } break; case Register64.RSI: if (usableX64Opcodes.xorRsi.Count > 0 && usableX64Opcodes.xorRsi.ElementAt(0).Value.Length <= 19) { byte[] gadget1 = BitConverter.GetBytes((long)usableX64Opcodes.xorRsi.ElementAt(0).Key).Reverse().ToArray(); return Tuple.Create(gadget1, usableX64Opcodes.xorRsi.ElementAt(0).Value, Register64.RSI); } break; case Register64.RDI: if (usableX64Opcodes.xorRdi.Count > 0 && usableX64Opcodes.xorRdi.ElementAt(0).Value.Length <= 19) { byte[] gadget1 = BitConverter.GetBytes((long)usableX64Opcodes.xorRdi.ElementAt(0).Key).Reverse().ToArray(); return Tuple.Create(gadget1, usableX64Opcodes.xorRdi.ElementAt(0).Value, Register64.RDI); } break; default: break; } return null; } #endregion #region GetAddInstruction /// /// Finds a add instruction going from the src register to the destination register /// /// The destination register /// The source register /// Returns a tuple of byte[], string, Register64 containing a pointer to the instruction and the associated mnemonics private Tuple GetAddInstruction(Register64 destReg, Register64 srcReg) { for (int i = 0; i < usableX64Opcodes.add.Count; i++) { string[] gadgetElements = usableX64Opcodes.add.ElementAt(i).Value.Split(','); if (gadgetElements[0].Contains(destReg.ToString().ToLower())) { var reg = registerIdentifier64(gadgetElements[1]); if (reg == srcReg) { return Tuple.Create(BitConverter.GetBytes((long)usableX64Opcodes.add.ElementAt(i).Key).Reverse().ToArray(), usableX64Opcodes.add.ElementAt(i).Value, reg); } } } return null; } #endregion #region GetSubInstruction /// /// Finds a sub instruction going from the src register to the destination register /// /// The destination register /// The source register /// Returns a tuple of byte[], string, Register64 containing a pointer to the instruction and the associated mnemonics private Tuple GetSubInstruction(Register64 destReg, Register64 srcReg) { for (int i = 0; i < usableX64Opcodes.sub.Count; i++) { string[] gadgetElements = usableX64Opcodes.sub.ElementAt(i).Value.Split(','); if (gadgetElements[0].Contains(destReg.ToString().ToLower())) { var reg = registerIdentifier64(gadgetElements[1]); if (reg == srcReg) { return Tuple.Create(BitConverter.GetBytes((long)usableX64Opcodes.sub.ElementAt(i).Key).Reverse().ToArray(), usableX64Opcodes.sub.ElementAt(i).Value, reg); } } } return null; } #endregion #region GetMovInstruction 64 bit /// /// Finds a mov instruction going from the src register to the destination register /// /// The destination register /// The source register /// The RegisterModifiers64 object. /// Returns a dictionary of byte[] string containing a pointer to the instruction and the associated mnemonics private Tuple GetMovInstruction(Register64 destReg, Register64 srcReg, RegisterModifiers64 regModified64) { for (int i = 0; i < usableX64Opcodes.mov.Count; i++) { string[] gadgetElements = usableX64Opcodes.mov.ElementAt(i).Value.Split(','); if (gadgetElements[0].Contains(destReg.ToString())) { var reg = registerIdentifier64(gadgetElements[1]); if (reg == srcReg) { return Tuple.Create(BitConverter.GetBytes((long)usableX64Opcodes.mov.ElementAt(i).Key).Reverse().ToArray(), usableX64Opcodes.mov.ElementAt(i).Value, reg); } } } return null; } #endregion #region registerIdentifier64 private Register64 registerIdentifier64(string reg) { switch (reg) { case " rax": return Register64.RAX; case " rbx": return Register64.RBX; case " rcx": return Register64.RCX; case " rdx": return Register64.RDX; case " rbp": return Register64.RBP; case " rsp": return Register64.RSP; case " rsi": return Register64.RSI; case " rdi": return Register64.RDI; case " r8": return Register64.R8; case " r9": return Register64.R9; case " r10": return Register64.R10; case " r11": return Register64.R11; case " r12": return Register64.R12; case " r13": return Register64.R13; case " r14": return Register64.R14; case " r15": return Register64.R15; default: return Register64.NONE; } } #endregion #region CompleteRegisters64 private bool CompleteRegisters64(Register64 regState64) { bool complete = true; if (!regState64.HasFlag(Register64.RAX)) { return false; } if (!regState64.HasFlag(Register64.RBX)) { return false; } if (!regState64.HasFlag(Register64.RCX)) { return false; } if (!regState64.HasFlag(Register64.RDX)) { return false; } if (!regState64.HasFlag(Register64.RBP)) { return false; } if (!regState64.HasFlag(Register64.RSP)) { return false; } if (!regState64.HasFlag(Register64.RSI)) { return false; } if (!regState64.HasFlag(Register64.RDI)) { return false; } if (!regState64.HasFlag(Register64.R8)) { return false; } if (!regState64.HasFlag(Register64.R9)) { return false; } if (!regState64.HasFlag(Register64.R10)) { return false; } if (!regState64.HasFlag(Register64.R11)) { return false; } if (!regState64.HasFlag(Register64.R12)) { return false; } if (!regState64.HasFlag(Register64.R13)) { return false; } if (!regState64.HasFlag(Register64.R14)) { return false; } if (!regState64.HasFlag(Register64.R15)) { return false; } return complete; } #endregion #region Register64 private enum Register64 { NONE = 0, [Description(" rax")] RAX = 1, [Description(" rbx")] RBX = 2, [Description(" rcx")] RCX = 4, [Description(" rdx")] RDX = 8, [Description(" rbp")] RBP = 16, [Description(" rsp")] RSP = 32, [Description(" rsi")] RSI = 64, [Description(" rdi")] RDI = 128, [Description(" r8")] R8 = 256, [Description(" r9")] R9 = 512, [Description(" r10")] R10 = 1024, [Description(" r11")] R11 = 2048, [Description(" r12")] R12 = 4096, [Description(" r13")] R13 = 8192, [Description(" r14")] R14 = 16384, [Description(" r15")] R15 = 32768 } #endregion private class RegisterModifiers64 { public Register64 RAX; public Register64 RBX; public Register64 RCX; public Register64 RDX; public Register64 RBP; public Register64 RSP; public Register64 RSI; public Register64 RDI; public Register64 R8; public Register64 R9; public Register64 R10; public Register64 R11; public Register64 R12; public Register64 R13; public Register64 R14; public Register64 R15; } #region X64Lists /// /// Contains lists of instructions for specific registers. /// public class X64Lists { /// /// pushRax list. /// public Dictionary pushRax = new Dictionary(); /// /// pushRcx list. /// public Dictionary pushRcx = new Dictionary(); /// /// pushRdx list. /// public Dictionary pushRdx = new Dictionary(); /// /// pushRbx list. /// public Dictionary pushRbx = new Dictionary(); /// /// pushRsp list. /// public Dictionary pushRsp = new Dictionary(); /// /// pushRbp list. /// public Dictionary pushRbp = new Dictionary(); /// /// pushRsi list. /// public Dictionary pushRsi = new Dictionary(); /// /// pushRdi list. /// public Dictionary pushRdi = new Dictionary(); /// /// pushR8 list. /// public Dictionary pushR8 = new Dictionary(); /// /// pushR9 list. /// public Dictionary pushR9 = new Dictionary(); /// /// pushR10 list. /// public Dictionary pushR10 = new Dictionary(); /// /// pushR11 list. /// public Dictionary pushR11 = new Dictionary(); /// /// pushR12 list. /// public Dictionary pushR12 = new Dictionary(); /// /// pushR13 list. /// public Dictionary pushR13 = new Dictionary(); /// /// pushR14 list. /// public Dictionary pushR14 = new Dictionary(); /// /// pushR15 list. /// public Dictionary pushR15 = new Dictionary(); /// /// popRax list. /// public Dictionary popRax = new Dictionary(); /// /// popRbx list. /// public Dictionary popRbx = new Dictionary(); /// /// popRcx list. /// public Dictionary popRcx = new Dictionary(); /// /// popRdx list. /// public Dictionary popRdx = new Dictionary(); /// /// popRsp list. /// public Dictionary popRsp = new Dictionary(); /// /// popRbp list. /// public Dictionary popRbp = new Dictionary(); /// /// popRsi list. /// public Dictionary popRsi = new Dictionary(); /// /// popRdi list. /// public Dictionary popRdi = new Dictionary(); /// /// popR8 list. /// public Dictionary popR8 = new Dictionary(); /// /// popR9 list. /// public Dictionary popR9 = new Dictionary(); /// /// popR10 list. /// public Dictionary popR10 = new Dictionary(); /// /// popR11 list. /// public Dictionary popR11 = new Dictionary(); /// /// popR12 list. /// public Dictionary popR12 = new Dictionary(); /// /// popR13 list. /// public Dictionary popR13 = new Dictionary(); /// /// popR14 list. /// public Dictionary popR14 = new Dictionary(); /// /// popR15 list. /// public Dictionary popR15 = new Dictionary(); /// /// xorRax list. /// public Dictionary xorRax = new Dictionary(); /// /// xorRbx list. /// public Dictionary xorRbx = new Dictionary(); /// /// xorRcx list. /// public Dictionary xorRcx = new Dictionary(); /// /// xorRdx list. /// public Dictionary xorRdx = new Dictionary(); /// /// xorRsi list. /// public Dictionary xorRsi = new Dictionary(); /// /// xorRdi list. /// public Dictionary xorRdi = new Dictionary(); /// /// xorRsp list. /// public Dictionary xorRsp = new Dictionary(); /// /// xorRbp list. /// public Dictionary xorRbp = new Dictionary(); /// /// xorR8 list. /// public Dictionary xorR8 = new Dictionary(); /// /// xorR9 list. /// public Dictionary xorR9 = new Dictionary(); /// /// xorR10 list. /// public Dictionary xorR10 = new Dictionary(); /// /// xorR11 list. /// public Dictionary xorR11 = new Dictionary(); /// /// xorR12 list. /// public Dictionary xorR12 = new Dictionary(); /// /// xorR13 list. /// public Dictionary xorR13 = new Dictionary(); /// /// xorR14 list. /// public Dictionary xorR14 = new Dictionary(); /// /// xorR15 list. /// public Dictionary xorR15 = new Dictionary(); /// /// jmpRsp list. /// public Dictionary jmpRsp = new Dictionary(); /// /// callRsp list. /// public Dictionary callRsp = new Dictionary(); /// /// incRax list. /// public Dictionary incRax = new Dictionary(); /// /// incRbx list. /// public Dictionary incRbx = new Dictionary(); /// /// incRcx list. /// public Dictionary incRcx = new Dictionary(); /// /// incRdx list. /// public Dictionary incRdx = new Dictionary(); /// /// incRbp list. /// public Dictionary incRbp = new Dictionary(); /// /// incRsp list. /// public Dictionary incRsp = new Dictionary(); /// /// incRsi list. /// public Dictionary incRsi = new Dictionary(); /// /// incRdi list. /// public Dictionary incRdi = new Dictionary(); /// /// incR8 list. /// public Dictionary incR8 = new Dictionary(); /// /// incR9 list. /// public Dictionary incR9 = new Dictionary(); /// /// incR10 list. /// public Dictionary incR10 = new Dictionary(); /// /// incR11 list. /// public Dictionary incR11 = new Dictionary(); /// /// incR12 list. /// public Dictionary incR12 = new Dictionary(); /// /// incR13 list. /// public Dictionary incR13 = new Dictionary(); /// /// incR14 list. /// public Dictionary incR14 = new Dictionary(); /// /// incR15 list. /// public Dictionary incR15 = new Dictionary(); /// /// decRax list. /// public Dictionary decRax = new Dictionary(); /// /// decRbx list. /// public Dictionary decRbx = new Dictionary(); /// /// decRcx list. /// public Dictionary decRcx = new Dictionary(); /// /// decRdx list. /// public Dictionary decRdx = new Dictionary(); /// /// decRbp list. /// public Dictionary decRbp = new Dictionary(); /// /// decRsp list. /// public Dictionary decRsp = new Dictionary(); /// /// decRsi list. /// public Dictionary decRsi = new Dictionary(); /// /// decRdi list. /// public Dictionary decRdi = new Dictionary(); /// /// decR8 list. /// public Dictionary decR8 = new Dictionary(); /// /// decR9 list. /// public Dictionary decR9 = new Dictionary(); /// /// decR10 list. /// public Dictionary decR10 = new Dictionary(); /// /// decR11 list. /// public Dictionary decR11 = new Dictionary(); /// /// decR12 list. /// public Dictionary decR12 = new Dictionary(); /// /// decR13 list. /// public Dictionary decR13 = new Dictionary(); /// /// decR14 list. /// public Dictionary decR14 = new Dictionary(); /// /// decR15 list. /// public Dictionary decR15 = new Dictionary(); /// /// add list. /// public Dictionary add = new Dictionary(); /// /// mov list. /// public Dictionary mov = new Dictionary(); /// /// sub list. /// public Dictionary sub = new Dictionary(); /// /// jmpRax list. /// public Dictionary callRax = new Dictionary(); /// /// callRax list. /// public Dictionary jmpRax = new Dictionary(); } #endregion private class RegisterLists64 { public List> raxList = new List>(); public List> rbxList = new List>(); public List> rcxList = new List>(); public List> rdxList = new List>(); public List> rbpList = new List>(); public List> rspList = new List>(); public List> rsiList = new List>(); public List> rdiList = new List>(); public List> r8List = new List>(); public List> r9List = new List>(); public List> r10List = new List>(); public List> r11List = new List>(); public List> r12List = new List>(); public List> r13List = new List>(); public List> r14List = new List>(); public List> r15List = new List>(); } /// /// Enum of methods which can be used to generate a ROP chain. /// [Flags] public enum RopMethod : ushort { [Description(" VirtualAlloc")] VirtualAlloc = 1, [Description(" HeapCreate")] HeapCreate = 2, [Description(" VirtualProtect")] VirtualProtect = 4, [Description(" WriteProcessMemory")] WriteProcessMemory = 8, [Description(" All")] All = 15 } } } ================================================ FILE: ERC/ERC/Thread_Info.cs ================================================ using ERC.Structures; using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.IO; using System.Linq; using System.Runtime.InteropServices; using System.Text; namespace ERC { /// /// Stores information about the current thread. /// public class ThreadInfo { #region Variables /// /// A handle for the current thread. /// public IntPtr ThreadHandle { get; private set; } /// /// The ID number of the current thread. /// public int ThreadID { get; private set; } /// /// x86 CPU Register values. /// public CONTEXT32 Context32; /// /// x64 CPU Register values. /// public CONTEXT64 Context64; internal bool ThreadFailed { get; private set; } internal MachineType X64 { get; set; } private ProcessThread ThreadCurrent { get; set; } private ProcessInfo ThreadProcess { get; set; } private ErcCore ThreadCore { get; set; } private ThreadBasicInformation ThreadBasicInfo = new ThreadBasicInformation(); private TEB Teb; private List> SehChain; #endregion #region Constructor internal ThreadInfo(ProcessThread thread, ErcCore core, ProcessInfo process) { ThreadID = thread.Id; ThreadCurrent = thread; ThreadCore = core; ThreadProcess = process; if (process.ProcessMachineType == MachineType.x64) { X64 = MachineType.x64; } else if(process.ProcessMachineType == MachineType.I386) { X64 = MachineType.I386; } try { ThreadHandle = ErcCore.OpenThread(ThreadAccess.All_ACCESS, false, (uint)thread.Id); if(ThreadHandle == null) { ThreadFailed = true; throw new ERCException(new Win32Exception(Marshal.GetLastWin32Error()).Message); } } catch(ERCException e) { ErcResult exceptionThrower = new ErcResult(ThreadCore) { Error = e }; exceptionThrower.LogEvent(); } var errorCheck = PopulateTEB(); if (errorCheck.Error != null && errorCheck.Error.Message != "Error: No SEH chain has been generated yet. An SEH chain will not be generated until a crash occurs.") { throw errorCheck.Error; } } #endregion #region Get Thread Context /// /// Gets the register values of a thread and populates the CONTEXT structs. Should only be used on a suspended thread, results on an active thread are unreliable. /// /// Returns an ErcResult, the return value can be ignored, the object should only be checked for error values public ErcResult Get_Context() { ErcResult result = new ErcResult(ThreadCore); if(X64 == MachineType.x64) { Context64 = new CONTEXT64(); Context64.ContextFlags = CONTEXT_FLAGS.CONTEXT_ALL; try { bool returnVar = ErcCore.GetThreadContext64(ThreadHandle, ref Context64); if (returnVar == false) { throw new ERCException("Win32 Exception encountered when attempting to get thread context: " + new Win32Exception(Marshal.GetLastWin32Error()).Message); } } catch (ERCException e) { result.Error = e; result.LogEvent(); return result; } catch(Exception e) { result.Error = e; result.LogEvent(e); } } else if(Environment.Is64BitOperatingSystem == true && X64 != MachineType.x64) { Context32 = new CONTEXT32(); Context32.ContextFlags = CONTEXT_FLAGS.CONTEXT_ALL; try { bool returnVar = ErcCore.Wow64GetThreadContext(ThreadHandle, ref Context32); if (returnVar == false) { throw new ERCException("Win32 Exception encountered when attempting to get thread context: " + new Win32Exception(Marshal.GetLastWin32Error()).Message); } } catch (ERCException e) { result.Error = e; result.LogEvent(); return result; } catch (Exception e) { result.Error = e; result.LogEvent(e); } } else { Context32 = new CONTEXT32(); Context32.ContextFlags = CONTEXT_FLAGS.CONTEXT_ALL; try { bool returnVar = ErcCore.GetThreadContext32(ThreadHandle, ref Context32); if (returnVar == false) { throw new ERCException("Win32 Exception encountered when attempting to get thread context: " + new Win32Exception(Marshal.GetLastWin32Error()).Message); } } catch (ERCException e) { result.Error = e; result.LogEvent(); return result; } catch (Exception e) { result.Error = e; result.LogEvent(e); } } return result; } #endregion #region Thread Environment Block #region Populate TEB internal ErcResult PopulateTEB() { ErcResult returnString = new ErcResult(ThreadCore); var retInt = ErcCore.ZwQueryInformationThread(ThreadHandle, 0, ref ThreadBasicInfo, Marshal.SizeOf(typeof(ThreadBasicInformation)), IntPtr.Zero); if (retInt != 0) { returnString.Error = new ERCException("NTSTATUS Error was thrown: 0x" + retInt.ToString("X")); return returnString; } byte[] tebBytes; int ret = 0; if(X64 == MachineType.x64) { tebBytes = new byte[0x16A0]; ErcCore.ReadProcessMemory(ThreadProcess.ProcessHandle, ThreadBasicInfo.TebBaseAdress, tebBytes, 0x16A0, out ret); } else { tebBytes = new byte[3888]; ErcCore.ReadProcessMemory(ThreadProcess.ProcessHandle, ThreadBasicInfo.TebBaseAdress, tebBytes, 3888, out ret); } if (ret == 0) { ERCException e = new ERCException("System error: An error occured when executing ReadProcessMemory\n Process Handle = 0x" + ThreadProcess.ProcessHandle.ToString("X") + "\nTEB Base Address = 0x" + ThreadBasicInfo.TebBaseAdress.ToString("X") + "\nWin32Error = " + Utilities.Win32Errors.GetLastWin32Error()); returnString.Error = e; return returnString; } if (X64 == MachineType.x64) { PopulateTEBStruct64(tebBytes); } else { PopulateTEBStruct32(tebBytes); } var bSehChain = BuildSehChain(); if(bSehChain.Error != null) { returnString.Error = bSehChain.Error; return returnString; } return returnString; } #endregion #region PopulateTebStruct private void PopulateTEBStruct32(byte[] tebBytes) { Teb = new TEB(); Teb.CurrentSehFrame = (IntPtr)BitConverter.ToInt32(tebBytes, 0x0); Teb.TopOfStack = (IntPtr)BitConverter.ToInt32(tebBytes, 0x4); Teb.BottomOfStack = (IntPtr)BitConverter.ToInt32(tebBytes, 0x8); Teb.SubSystemTeb = (IntPtr)BitConverter.ToInt32(tebBytes, 0xC); Teb.FiberData = (IntPtr)BitConverter.ToInt32(tebBytes, 0x10); Teb.ArbitraryDataSlot = (IntPtr)BitConverter.ToInt32(tebBytes, 0x14); Teb.Teb = (IntPtr)BitConverter.ToInt32(tebBytes, 0x18); Teb.EnvironmentPointer = (IntPtr)BitConverter.ToInt32(tebBytes, 0x1C); Teb.Identifiers.ProcessId = (IntPtr)BitConverter.ToInt32(tebBytes, 0x20); Teb.Identifiers.ThreadId = (IntPtr)BitConverter.ToInt32(tebBytes, 0x24); Teb.RpcHandle = (IntPtr)BitConverter.ToInt32(tebBytes, 0x28); Teb.Tls = (IntPtr)BitConverter.ToInt32(tebBytes, 0x2C); Teb.Peb = (IntPtr)BitConverter.ToInt32(tebBytes, 0x30); Teb.LastErrorNumber = BitConverter.ToInt32(tebBytes, 0x34); Teb.CriticalSectionsCount = BitConverter.ToInt32(tebBytes, 0x38); Teb.CsrClientThread = (IntPtr)BitConverter.ToInt32(tebBytes, 0x3C); Teb.Win32ThreadInfo = (IntPtr)BitConverter.ToInt32(tebBytes, 0x40); Teb.Win32ClientInfo = new byte[4]; Array.Copy(tebBytes, 0x44, Teb.Win32ClientInfo, 0, 4); Teb.WoW64Reserved = (IntPtr)BitConverter.ToInt32(tebBytes, 0xC0); Teb.CurrentLocale = (IntPtr)BitConverter.ToInt32(tebBytes, 0xC4); Teb.FpSoftwareStatusRegister = (IntPtr)BitConverter.ToInt32(tebBytes, 0xC8); Teb.SystemReserved1 = new byte[216]; Array.Copy(tebBytes, 0xCC, Teb.SystemReserved1, 0, 216); Teb.ExceptionCode = (IntPtr)BitConverter.ToInt32(tebBytes, 0x1A4); Teb.ActivationContextStack = new byte[4]; Array.Copy(tebBytes, 0x1A8, Teb.ActivationContextStack, 0, 4); Teb.SpareBytes = new byte[24]; Array.Copy(tebBytes, 0x1BC, Teb.SpareBytes, 0, 24); Teb.SystemReserved2 = new byte[40]; Array.Copy(tebBytes, 0x1D4, Teb.SystemReserved2, 0, 40); Teb.GdiTebBatch = new byte[1248]; Array.Copy(tebBytes, 0x1FC, Teb.GdiTebBatch, 0, 1248); Teb.GdiRegion = (IntPtr)BitConverter.ToInt32(tebBytes, 0x6DC); Teb.GdiPen = (IntPtr)BitConverter.ToInt32(tebBytes, 0x6E0); Teb.GdiBrush = (IntPtr)BitConverter.ToInt32(tebBytes, 0x6E4); Teb.RealProcessId = BitConverter.ToInt32(tebBytes, 0x6E8); Teb.RealThreadId = BitConverter.ToInt32(tebBytes, 0x6EC); Teb.GdiCachedProcessHandle = (IntPtr)BitConverter.ToInt32(tebBytes, 0x6F0); Teb.GdiClientProcessId = (IntPtr)BitConverter.ToInt32(tebBytes, 0x6F4); Teb.GdiClientThreadId = (IntPtr)BitConverter.ToInt32(tebBytes, 0x6F8); Teb.GdiThreadLocalInfo = (IntPtr)BitConverter.ToInt32(tebBytes, 0x6FC); Teb.UserReserved1 = new byte[20]; Array.Copy(tebBytes, 0x700, Teb.UserReserved1, 0, 20); Teb.GlReserved1 = new byte[1248]; Array.Copy(tebBytes, 0x714, Teb.GlReserved1, 0, 1248); Teb.LastStatusValue = BitConverter.ToInt32(tebBytes, 0xBF4); Teb.StaticUnicodeString = new byte[214]; Array.Copy(tebBytes, 0xBF8, Teb.StaticUnicodeString, 0, 214); Teb.DeallocationStack = (IntPtr)BitConverter.ToInt32(tebBytes, 0xE0C); Teb.TlsSlots = new byte[100]; Array.Copy(tebBytes, 0xE10, Teb.TlsSlots, 0, 100); Teb.TlsLinks = BitConverter.ToInt32(tebBytes, 0xF10); Teb.Vdm = (IntPtr)BitConverter.ToInt32(tebBytes, 0xF18); Teb.RpcReserved = (IntPtr)BitConverter.ToInt32(tebBytes, 0xF1C); Teb.ThreadErrorMode = (IntPtr)BitConverter.ToInt32(tebBytes, 0xF28); } private void PopulateTEBStruct64(byte[] tebBytes) { Teb = new TEB(); Teb.CurrentSehFrame = (IntPtr)BitConverter.ToInt64(tebBytes, 0x0); Teb.TopOfStack = (IntPtr)BitConverter.ToInt64(tebBytes, 0x8); Teb.BottomOfStack = (IntPtr)BitConverter.ToInt64(tebBytes, 0x10); Teb.SubSystemTeb = (IntPtr)BitConverter.ToInt64(tebBytes, 0x18); Teb.FiberData = (IntPtr)BitConverter.ToInt64(tebBytes, 0x20); Teb.ArbitraryDataSlot = (IntPtr)BitConverter.ToInt64(tebBytes, 0x28); Teb.Teb = (IntPtr)BitConverter.ToInt64(tebBytes, 0x30); Teb.EnvironmentPointer = (IntPtr)BitConverter.ToInt64(tebBytes, 0x38); Teb.Identifiers.ProcessId = (IntPtr)BitConverter.ToInt64(tebBytes, 0x40); Teb.Identifiers.ThreadId = (IntPtr)BitConverter.ToInt64(tebBytes, 0x48); Teb.RpcHandle = (IntPtr)BitConverter.ToInt64(tebBytes, 0x50); Teb.Tls = (IntPtr)BitConverter.ToInt64(tebBytes, 0x58); Teb.Peb = (IntPtr)BitConverter.ToInt64(tebBytes, 0x60); Teb.LastErrorNumber = BitConverter.ToInt32(tebBytes, 0x68); Teb.CriticalSectionsCount = BitConverter.ToInt32(tebBytes, 0x6C); Teb.CsrClientThread = (IntPtr)BitConverter.ToInt64(tebBytes, 0x70); Teb.Win32ThreadInfo = (IntPtr)BitConverter.ToInt64(tebBytes, 0x78); Teb.Win32ClientInfo = new byte[4]; Array.Copy(tebBytes, 0x80, Teb.Win32ClientInfo, 0, 4); Teb.CurrentLocale = (IntPtr)BitConverter.ToInt64(tebBytes, 0x84); Teb.FpSoftwareStatusRegister = (IntPtr)BitConverter.ToInt64(tebBytes, 0x8C); Teb.SystemReserved1 = new byte[216]; Array.Copy(tebBytes, 0x94, Teb.SystemReserved1, 0, 216); Teb.ExceptionCode = (IntPtr)BitConverter.ToInt64(tebBytes, 0x16C); Teb.ActivationContextStack = new byte[4]; Array.Copy(tebBytes, 0x174, Teb.ActivationContextStack, 0, 4); Teb.SpareBytes = new byte[24]; Array.Copy(tebBytes, 0x178, Teb.SpareBytes, 0, 24); Teb.SystemReserved2 = new byte[40]; Array.Copy(tebBytes, 0x190, Teb.SystemReserved2, 0, 40); Teb.GdiTebBatch = new byte[1248]; Array.Copy(tebBytes, 0x1b8, Teb.GdiTebBatch, 0, 1248); Teb.GdiRegion = (IntPtr)BitConverter.ToInt64(tebBytes, 0x698); Teb.GdiPen = (IntPtr)BitConverter.ToInt64(tebBytes, 0x6A0); Teb.GdiBrush = (IntPtr)BitConverter.ToInt64(tebBytes, 0x6A8); Teb.RealProcessId = BitConverter.ToInt32(tebBytes, 0x6B0); Teb.RealThreadId = BitConverter.ToInt32(tebBytes, 0x6B4); Teb.GdiCachedProcessHandle = (IntPtr)BitConverter.ToInt64(tebBytes, 0x6B8); Teb.GdiClientProcessId = (IntPtr)BitConverter.ToInt64(tebBytes, 0x6C0); Teb.GdiClientThreadId = (IntPtr)BitConverter.ToInt64(tebBytes, 0x6C8); Teb.GdiThreadLocalInfo = (IntPtr)BitConverter.ToInt64(tebBytes, 0x6D0); Teb.UserReserved1 = new byte[20]; Array.Copy(tebBytes, 0x6D8, Teb.UserReserved1, 0, 20); Teb.GlReserved1 = new byte[1248]; Array.Copy(tebBytes, 0x6EC, Teb.GlReserved1, 0, 1248); Teb.LastStatusValue = BitConverter.ToInt32(tebBytes, 0x1250); Teb.StaticUnicodeString = new byte[214]; Array.Copy(tebBytes, 0x1258, Teb.StaticUnicodeString, 0, 214); Teb.DeallocationStack = (IntPtr)BitConverter.ToInt64(tebBytes, 0x1478); Teb.TlsSlots = new byte[520]; Array.Copy(tebBytes, 0x1480, Teb.TlsSlots, 0, 520); Teb.TlsLinks = BitConverter.ToInt64(tebBytes, 0x1680); Teb.Vdm = (IntPtr)BitConverter.ToInt64(tebBytes, 0x1688); Teb.RpcReserved = (IntPtr)BitConverter.ToInt64(tebBytes, 0x1690); Teb.ThreadErrorMode = (IntPtr)BitConverter.ToInt64(tebBytes, 0x1698); } #endregion #region BuildSehChain internal ErcResult>> BuildSehChain() { ErcResult>> sehList = new ErcResult>>(ThreadCore); sehList.ReturnValue = new List>(); if (Teb.Equals(default(TEB))) { sehList.Error = new Exception("Error: TEB structure for this thread has not yet been populated. Call PopulateTEB first"); return sehList; } if(Teb.CurrentSehFrame == IntPtr.Zero) { sehList.Error = new Exception("Error: No SEH chain has been generated yet. An SEH chain will not be generated until a crash occurs."); return sehList; } byte[] sehEntry; byte[] sehFinal; int arraySize = 0; if(X64 == MachineType.x64) { arraySize = 8; sehEntry = new byte[arraySize]; sehFinal = new byte[arraySize]; sehEntry = BitConverter.GetBytes((long)Teb.CurrentSehFrame); } else { arraySize = 4; sehEntry = new byte[arraySize]; sehFinal = new byte[arraySize]; sehEntry = BitConverter.GetBytes((int)Teb.CurrentSehFrame); } for (int i = 0; i < sehFinal.Length; i++) { sehFinal[i] = 0xFF; } byte[] prevSEH = new byte[] { 0xFF }; string pattern_standard = File.ReadAllText(ThreadCore.PatternStandardPath); string pattern_extended = File.ReadAllText(ThreadCore.PatternExtendedPath); while (!sehEntry.SequenceEqual(sehFinal)) { byte[] reversedSehEntry = new byte[arraySize]; byte[] nSeh = new byte[arraySize]; byte[] sehHolder = new byte[arraySize * 2]; int ret = 0; if(X64 == MachineType.x64) { ret = ErcCore.ReadProcessMemory(ThreadProcess.ProcessHandle, (IntPtr)BitConverter.ToInt64(sehEntry, 0), sehHolder, arraySize * 2, out int retInt); Array.Copy(sehHolder, 0, sehEntry, 0, arraySize); Array.Copy(sehHolder, arraySize, nSeh, 0, arraySize); } else { ret = ErcCore.ReadProcessMemory(ThreadProcess.ProcessHandle, (IntPtr)BitConverter.ToInt32(sehEntry, 0), sehHolder, arraySize * 2, out int retInt); Array.Copy(sehHolder, 0, sehEntry, 0, arraySize); Array.Copy(sehHolder, arraySize, nSeh, 0, arraySize); } if (ret != 0 && ret != 1) { ERCException e = new ERCException("System error: An error occured when executing ReadProcessMemory\n Process Handle = 0x" + ThreadProcess.ProcessHandle.ToString("X") + " TEB Current Seh = 0x" + Teb.CurrentSehFrame.ToString("X") + " Return value = " + ret + Environment.NewLine + "Win32Exception: " + new Win32Exception(Marshal.GetLastWin32Error()).Message); sehList.Error = e; sehList.LogEvent(); return sehList; } Array.Reverse(nSeh); for(int i = 0; i < sehEntry.Length; i++) { reversedSehEntry[i] = sehEntry[i]; } Array.Reverse(reversedSehEntry, 0, reversedSehEntry.Length); if (prevSEH.SequenceEqual(reversedSehEntry)) { sehEntry = new byte[sehFinal.Length]; Array.Copy(sehFinal, 0, sehEntry, 0, sehFinal.Length); } else if (!sehEntry.SequenceEqual(sehFinal) && !sehList.ReturnValue.Any(e => e.Item1.SequenceEqual(reversedSehEntry))) { Tuple tuple = new Tuple(reversedSehEntry, nSeh); sehList.ReturnValue.Add(tuple); } if (pattern_standard.Contains(Encoding.Unicode.GetString(reversedSehEntry)) || pattern_extended.Contains(Encoding.Unicode.GetString(reversedSehEntry))) { sehEntry = new byte[sehFinal.Length]; Array.Copy(sehFinal, 0, sehEntry, 0, sehFinal.Length); } if (pattern_standard.Contains(Encoding.ASCII.GetString(reversedSehEntry)) || pattern_extended.Contains(Encoding.ASCII.GetString(reversedSehEntry))) { sehEntry = new byte[sehFinal.Length]; Array.Copy(sehFinal, 0, sehEntry, 0, sehFinal.Length); } if (pattern_standard.Contains(Encoding.UTF32.GetString(reversedSehEntry)) || pattern_extended.Contains(Encoding.UTF32.GetString(reversedSehEntry))) { sehEntry = new byte[sehFinal.Length]; Array.Copy(sehFinal, 0, sehEntry, 0, sehFinal.Length); } if (pattern_standard.Contains(Encoding.UTF7.GetString(reversedSehEntry)) || pattern_extended.Contains(Encoding.UTF7.GetString(reversedSehEntry))) { sehEntry = new byte[sehFinal.Length]; Array.Copy(sehFinal, 0, sehEntry, 0, sehFinal.Length); } if (pattern_standard.Contains(Encoding.UTF8.GetString(reversedSehEntry)) || pattern_extended.Contains(Encoding.UTF8.GetString(reversedSehEntry))) { sehEntry = new byte[sehFinal.Length]; Array.Copy(sehFinal, 0, sehEntry, 0, sehFinal.Length); } prevSEH = new byte[reversedSehEntry.Length]; Array.Copy(reversedSehEntry, 0, prevSEH, 0, reversedSehEntry.Length); } SehChain = new List>(sehList.ReturnValue); return sehList; } #endregion #endregion #region Accessors /// /// Gets the current SEH chain for the process. /// /// Returns a list of IntPtr containing the SEH chain public List> GetSehChain() { List> SehPtrs = new List>(); var pteb = PopulateTEB(); if (pteb.Error != null) { throw pteb.Error; } if(SehChain == null) { throw new Exception("Error: No SEH chain has been generated yet. An SEH chain will not be generated until a crash occurs."); } if(X64 == MachineType.x64) { for (int i = 0; i < SehChain.Count; i++) { Tuple tuple = new Tuple((IntPtr)BitConverter.ToInt64(SehChain[i].Item1, 0), (IntPtr)BitConverter.ToInt64(SehChain[i].Item2, 0)); SehPtrs.Add(tuple); } } else { for (int i = 0; i < SehChain.Count; i++) { Tuple tuple = new Tuple((IntPtr)BitConverter.ToInt32(SehChain[i].Item1, 0), (IntPtr)BitConverter.ToInt32(SehChain[i].Item2, 0)); SehPtrs.Add(tuple); } } return SehPtrs; } /// /// Gets the Thread environment block of the current thread. /// /// Returns a TEB struct public TEB GetTeb() { if (Teb.Equals(default(TEB))) { throw new Exception("Error: TEB structure for this thread has not yet been populated. Call PopulateTEB first"); } return Teb; } /// /// Gets information specific to the current thread and returns it as a string. /// /// Returns a string public override string ToString() { string ret = ""; if(X64 == MachineType.x64) { ret += "Thread Handle = " + "0x" + ThreadHandle.ToString("x16") + Environment.NewLine; } else { ret += "Thread Handle = " + "0x" + ThreadHandle.ToString("x8") + Environment.NewLine; } ret += "Thread ID = " + ThreadID + Environment.NewLine; ret += "Thread is running in a 64 bit process = " + X64 + Environment.NewLine; ret += "Thread Parent Process = " + ThreadProcess.ProcessName; if(!Context32.Equals(default(CONTEXT32)) && X64 == MachineType.I386) { ret += "Thread Context32 = Populated" + Environment.NewLine; } else if(!Context64.Equals(default(CONTEXT64)) && X64 == MachineType.x64) { ret += "Thread Context64 = Populated" + Environment.NewLine; } else if(X64 == MachineType.x64) { ret += "Thread Context64 = Unpopulated" + Environment.NewLine; } else { ret += "Thread Context32 = Unpopulated" + Environment.NewLine; } if (!Teb.Equals(default(TEB))) { ret += "Thread TEB = Populated" + Environment.NewLine; } else { ret += "Thread TEB = Unpopulated" + Environment.NewLine; } return ret; } #endregion } } ================================================ FILE: ERC/ERC/Win32Errors.cs ================================================ using System; using System.Runtime.InteropServices; namespace ERC.Utilities { public static class Win32Errors { #region definitions [DllImport("kernel32.dll", SetLastError = true)] static extern IntPtr LocalFree(IntPtr hMem); [DllImport("kernel32.dll", SetLastError = true)] static extern int FormatMessage(FormatMessageFlags dwFlags, IntPtr lpSource, uint dwMessageId, uint dwLanguageId, ref IntPtr lpBuffer, uint nSize, IntPtr Arguments); [Flags] private enum FormatMessageFlags : uint { FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x00000100, FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200, FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000, FORMAT_MESSAGE_ARGUMENT_ARRAY = 0x00002000, FORMAT_MESSAGE_FROM_HMODULE = 0x00000800, FORMAT_MESSAGE_FROM_STRING = 0x00000400, } #endregion /// /// Gets a user friendly string message for a system error code /// /// Error string public static string GetLastWin32Error(int errorCode = 0) { if (errorCode == 0) { errorCode = Marshal.GetLastWin32Error(); } try { IntPtr lpMsgBuf = IntPtr.Zero; int dwChars = FormatMessage( FormatMessageFlags.FORMAT_MESSAGE_ALLOCATE_BUFFER | FormatMessageFlags.FORMAT_MESSAGE_FROM_SYSTEM | FormatMessageFlags.FORMAT_MESSAGE_IGNORE_INSERTS, IntPtr.Zero, (uint)errorCode, 0, // Default language ref lpMsgBuf, 0, IntPtr.Zero); if (dwChars == 0) { // Handle the error. int le = Marshal.GetLastWin32Error(); return "Unable to get error code string from System - Error " + le.ToString(); } string sRet = Marshal.PtrToStringAnsi(lpMsgBuf); // Free the buffer. lpMsgBuf = LocalFree(lpMsgBuf); return sRet; } catch (Exception e) { return "Unable to get error code string from System -> " + e.ToString(); } } } } ================================================ FILE: ERC/LICENSE ================================================ GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . ================================================ FILE: ERC/README.md ================================================ # ERC.Net [![License](https://img.shields.io/github/license/Andy53/ERC.Net)](license.txt) [![GitHub issues](https://img.shields.io/github/issues-raw/Andy53/ERC.Net?style=flat)](https://github.com/Andy53/ERC.Net/issues) ERC.Net is a collection of tools designed to assist in debugging Windows application crashes. ERC.Net supports both 64 and 32 bit applications, can parse DLL/EXE headers, identify compile time flags such as ASLR, DEP and SafeSEH, generate non repeating patterns, generate platform specific egg hunters, identify process information such as loaded modules and running threads, read the TEB of a specific thread, assist with identifying numerous types of memory vulnerabilities and has numerous other use cases. ## Installing Install one of the nuget packages ([x86](https://www.nuget.org/packages/ERC.Net-x86/)/[x64](https://www.nuget.org/packages/ERC.Net-x64/)) or download the source code from [Github](https://github.com/Andy53/ERC.net), build the library and then link it in your project. ### Prerequisites Visual studio .Net 4.7.2 C# ### Documentation This library contains the fundamental specifications, documentation, and architecture that underpin ERC.Net. If you're looking to understand the system better, or want to know how to integrate the various components, there is a lot of valuable information contained here. [📄 Documentation and Specifications](https://andy53.github.io/ERC.net/) ### Getting Started Below are a set of examples detailing how to use the basic functionality provided by ERC.Net Creating a sting of non repeating characters: ```csharp using System; using ERC; using ERC.Utilities; namespace ERC_Test_App { class Program { static void Main() { ErcCore core = new ErcCore(); var p = PatternTools.PatternCreate(1000, core); Console.WriteLine("Pattern:" + Environment.NewLine + p.ReturnValue); Console.ReadKey(); } } } ``` Identifying the position of a sting within a non repeating string: ```csharp using System; using ERC; using ERC.Utilities; namespace ERC_Test_App { class Program { static void Main() { ErcCore core = new ErcCore(); var p = PatternTools.PatternOffset("Aa9", core); Console.WriteLine("Pattern Offset:" + Environment.NewLine + p.ReturnValue); Console.ReadKey(); } } } ``` Display a list of all applicable local processes: ```csharp using System; using System.Diagnostics; using ERC; namespace ERC_Test_App { class Program { static void Main() { ErcCore core = new ErcCore(); var test = ProcessInfo.ListLocalProcesses(core); foreach (Process process in test.ReturnValue) { Console.WriteLine("Name: {0} ID: {1}", process.ProcessName, process.Id); } Console.WriteLine(Environment.NewLine); Console.ReadKey(); } } } ``` Search Process Memory for a string (the string being searched for is "anonymous", the program being searched is notepad) and return a list of pointers to that string in process memory: ```csharp using System; using System.Collections.Generic; using System.Diagnostics; using ERC; namespace ERC_Test_App { class Program { static void Main() { ErcCore core = new ErcCore(); Process[] processes = Process.GetProcesses(); Process thisProcess = null; foreach (Process process1 in processes) { if (process1.ProcessName.Contains("notepad")) { thisProcess = process1; } } ProcessInfo info = new ProcessInfo(core, thisProcess); var listy = info.SearchMemory(1, searchString: "anonymous"); foreach (KeyValuePair s in listy.ReturnValue) { Console.WriteLine("0x" + s.Key.ToString("x16") + " Filepath: " + s.Value); } Console.ReadKey(); } } } ``` An example of how to assemble mnemonics into opcodes: ```csharp using System; using System.Collections.Generic; using ERC; namespace ERC_Test_App { class Program { static void Main() { List instructions = new List(); instructions.Add("ret"); foreach (string s in instructions) { List strings = new List(); strings.Add(s); var asmResult = ERC.Utilities.OpcodeAssembler.AssembleOpcodes(strings, MachineType.x64); Console.WriteLine(s + " = " + BitConverter.ToString(asmResult.ReturnValue).Replace("-", "")); } Console.ReadKey(); } } } ``` An example of how to disassemble opcodes into mnemonics: ```csharp using System; using ERC; namespace ERC_Test_App { class Program { static void Main() { byte[] opcodes = new byte[] { 0xC3 }; var result = ERC.Utilities.OpcodeDisassembler.Disassemble(opcodes, MachineType.x64); Console.WriteLine(result.ReturnValue + Environment.NewLine); Console.ReadKey(); } } } ``` Display information about all modules associated with a process: ```csharp using System; using ERC; using System.Diagnostics; using System.Collections.Generic; using ERC.Utilities; namespace ERC_test_app { class Program { static void Main(string[] args) { public static ErcCore core = new ErcCore(); Console.WriteLine("Outputting module info"); output_module_info(); Console.ReadKey(); } public static void output_module_info() { Process[] processes = Process.GetProcesses(); Process thisProcess = null; foreach (Process process1 in processes) { if (process1.ProcessName.Contains("notepad")) { thisProcess = process1; } } ProcessInfo info = new ProcessInfo(core, thisProcess); Console.WriteLine("Here"); Console.WriteLine(DisplayOutput.GenerateModuleInfoTable(info)); } } } ``` Generate a byte array of all possible bytes excluding 0xA1, 0xB1, 0xC1 and 0xD1 then save it to a file in C:\: ```csharp using System; using ERC; namespace ERC_Test_App { class Program { static void Main() { ErcCore core = new ErcCore(); byte[] unwantedBytes = new byte[] { 0xA1, 0xB1, 0xC1, 0xD1 }; var bytes = DisplayOutput.GenerateByteArray(unwantedBytes, core); Console.WriteLine(BitConverter.ToString(bytes).Replace("-", " ")); Console.ReadKey(); } } } ``` Return the value of all registers (Context) for a given thread: ```csharp using System; using System.Diagnostics; using ERC; namespace ERC_Test_App { class Program { static void Main() { ErcCore core = new ErcCore(); Process[] processes = Process.GetProcesses(); Process thisProcess = null; foreach (Process process1 in processes) { if (process1.ProcessName.Contains("notepad")) { thisProcess = process1; } } ProcessInfo info = new ProcessInfo(core, thisProcess); for (int i = 0; i < info.ThreadsInfo.Count; i++) { info.ThreadsInfo[i].Get_Context(); Console.WriteLine(info.ThreadsInfo[i].Context64.ToString()); } Console.ReadKey(); } } } ``` Return a pointer and mnemonics for all SEH jumps in the given process and associated modules: ```csharp using System; using System.Diagnostics; using ERC; namespace ERC_Test_App { class Program { static void Main() { ErcCore core = new ErcCore(); Process[] processes = Process.GetProcesses(); Process thisProcess = null; foreach (Process process1 in processes) { if (process1.ProcessName.Contains("notepad")) { thisProcess = process1; } } ProcessInfo info = new ProcessInfo(core, thisProcess); var tester = DisplayOutput.GetSEHJumps(info); foreach (string s in tester.ReturnValue) { Console.WriteLine(s); } Console.ReadKey(); } } } ``` Generate a collection of egghunters with the tag "AAAA": ```csharp using System; using ERC; namespace ERC_Test_App { class Program { static void Main() { ErcCore core = new ErcCore(); var eggs = DisplayOutput.GenerateEggHunters(core, "AAAA"); Console.WriteLine(eggs); Console.ReadKey(); } } } ``` Display the SEH chain for a thread (the process must have entered an error state for this to be populated): ```csharp using System; using System.Diagnostics; using ERC; namespace ERC_Test_App { class Program { static void Main() { ErcCore core = new ErcCore(); Process[] processes = Process.GetProcesses(); Process thisProcess = null; foreach (Process process1 in processes) { if (process1.ProcessName.Contains("notepad")) { thisProcess = process1; } } ProcessInfo info = new ProcessInfo(core, thisProcess); var test = info.ThreadsInfo[0].GetSehChain(); foreach (IntPtr i in test) { Console.WriteLine("Ptr: {0}", i.ToString("X8")); } Console.ReadKey(); } } } ``` Find a non repeating pattern in memory and display which registers point to (or near) it: ```csharp using System; using System.Diagnostics; using ERC; namespace ERC_Test_App { class Program { static void Main() { ErcCore core = new ErcCore(); Process[] processes = Process.GetProcesses(); Process thisProcess = null; foreach (Process process1 in processes) { if (process1.ProcessName.Contains("Vulnerable Application Name")) { thisProcess = process1; } } ProcessInfo info = new ProcessInfo(core, thisProcess); var strings = DisplayOutput.GenerateFindNRPTable(info, 2, false); foreach (string s in strings) { Console.WriteLine(s); } Console.ReadKey(); } } } ``` Generate a 32bit ROP chain for the current process: ```csharp using System; using ERC; using System.Diagnostics; using System.Collections.Generic; using ERC.Utilities; namespace ERC_test_app { class Program { static void Main(string[] args) { public static ErcCore core = new ErcCore(); Console.WriteLine("Generate RopChain 32"); GenerateRopChain32(); Console.ReadKey(); } public static void GenerateRopChain32() { Process[] processes = Process.GetProcesses(); Process thisProcess = null; foreach (Process process1 in processes) { if (process1.ProcessName.Contains("Word")) { thisProcess = process1; } } ProcessInfo info = new ProcessInfo(core, thisProcess); RopChainGenerator32 RCG = new RopChainGenerator32(info); RCG.GenerateRopChain32(); } } } ``` ## Versioning For the versions available, see the [tags on this repository](https://github.com/Andy53/ERC.net/tags). ## Authors * **Andy Bowden** - [Andy53](https://github.com/Andy53) ## License This project is licensed under the GNU General Public License v3.0 - see the [LICENSE.md](LICENSE.md) file for details ## Acknowledgments * Hat tip to anyone whose code was used * Inspiration * Other things ================================================ FILE: ERC/docs/api/ERC.DisplayOutput.html ================================================  Class DisplayOutput
================================================ FILE: ERC/docs/api/ERC.ERCException.html ================================================  Class ERCException
================================================ FILE: ERC/docs/api/ERC.ErcCore.html ================================================  Class ErcCore
================================================ FILE: ERC/docs/api/ERC.ErcResult-1.html ================================================  Class ErcResult<T>
================================================ FILE: ERC/docs/api/ERC.MachineType.html ================================================  Enum MachineType
================================================ FILE: ERC/docs/api/ERC.ModuleInfo.html ================================================  Class ModuleInfo
================================================ FILE: ERC/docs/api/ERC.ProcessInfo.html ================================================  Class ProcessInfo
================================================ FILE: ERC/docs/api/ERC.Structures.AllocationProtect.html ================================================  Enum AllocationProtect
================================================ FILE: ERC/docs/api/ERC.Structures.CONTEXT32.html ================================================  Struct CONTEXT32
================================================ FILE: ERC/docs/api/ERC.Structures.CONTEXT64.html ================================================  Struct CONTEXT64
================================================ FILE: ERC/docs/api/ERC.Structures.CONTEXT_FLAGS.html ================================================  Enum CONTEXT_FLAGS
================================================ FILE: ERC/docs/api/ERC.Structures.ClientID.html ================================================  Struct ClientID
================================================ FILE: ERC/docs/api/ERC.Structures.FLOATING_SAVE_AREA.html ================================================  Struct FLOATING_SAVE_AREA
================================================ FILE: ERC/docs/api/ERC.Structures.IMAGE_DATA_DIRECTORY.html ================================================  Struct IMAGE_DATA_DIRECTORY
================================================ FILE: ERC/docs/api/ERC.Structures.IMAGE_DOS_HEADER.html ================================================  Struct IMAGE_DOS_HEADER
================================================ FILE: ERC/docs/api/ERC.Structures.IMAGE_FILE_HEADER.html ================================================  Struct IMAGE_FILE_HEADER
================================================ FILE: ERC/docs/api/ERC.Structures.IMAGE_LOAD_CONFIG_CODE_INTEGRITY.html ================================================  Struct IMAGE_LOAD_CONFIG_CODE_INTEGRITY
================================================ FILE: ERC/docs/api/ERC.Structures.IMAGE_LOAD_CONFIG_DIRECTORY32.html ================================================  Struct IMAGE_LOAD_CONFIG_DIRECTORY32
================================================ FILE: ERC/docs/api/ERC.Structures.IMAGE_LOAD_CONFIG_DIRECTORY64.html ================================================  Struct IMAGE_LOAD_CONFIG_DIRECTORY64
================================================ FILE: ERC/docs/api/ERC.Structures.IMAGE_NT_HEADERS32.html ================================================  Struct IMAGE_NT_HEADERS32
================================================ FILE: ERC/docs/api/ERC.Structures.IMAGE_NT_HEADERS64.html ================================================  Struct IMAGE_NT_HEADERS64
================================================ FILE: ERC/docs/api/ERC.Structures.IMAGE_OPTIONAL_HEADER32.html ================================================  Struct IMAGE_OPTIONAL_HEADER32
================================================ FILE: ERC/docs/api/ERC.Structures.IMAGE_OPTIONAL_HEADER64.html ================================================  Struct IMAGE_OPTIONAL_HEADER64
================================================ FILE: ERC/docs/api/ERC.Structures.LIST_ENTRY.html ================================================  Struct LIST_ENTRY
================================================ FILE: ERC/docs/api/ERC.Structures.LOADED_IMAGE.html ================================================  Struct LOADED_IMAGE
================================================ FILE: ERC/docs/api/ERC.Structures.LoadLibraryFlags.html ================================================  Enum LoadLibraryFlags
================================================ FILE: ERC/docs/api/ERC.Structures.M128A.html ================================================  Struct M128A
================================================ FILE: ERC/docs/api/ERC.Structures.MEMORY_BASIC_INFORMATION32.html ================================================  Struct MEMORY_BASIC_INFORMATION32
================================================ FILE: ERC/docs/api/ERC.Structures.MEMORY_BASIC_INFORMATION64.html ================================================  Struct MEMORY_BASIC_INFORMATION64
================================================ FILE: ERC/docs/api/ERC.Structures.MagicType.html ================================================  Enum MagicType
================================================ FILE: ERC/docs/api/ERC.Structures.ProcessAccessFlags.html ================================================  Enum ProcessAccessFlags
================================================ FILE: ERC/docs/api/ERC.Structures.RegisterInfo.html ================================================  Class RegisterInfo
================================================ FILE: ERC/docs/api/ERC.Structures.StateEnum.html ================================================  Enum StateEnum
================================================ FILE: ERC/docs/api/ERC.Structures.SubSystemType.html ================================================  Enum SubSystemType
================================================ FILE: ERC/docs/api/ERC.Structures.TEB.html ================================================  Struct TEB
================================================ FILE: ERC/docs/api/ERC.Structures.ThreadAccess.html ================================================  Enum ThreadAccess
================================================ FILE: ERC/docs/api/ERC.Structures.ThreadBasicInformation.html ================================================  Struct ThreadBasicInformation
================================================ FILE: ERC/docs/api/ERC.Structures.TypeEnum.html ================================================  Enum TypeEnum
================================================ FILE: ERC/docs/api/ERC.Structures.XSAVE_FORMAT64.html ================================================  Struct XSAVE_FORMAT64
================================================ FILE: ERC/docs/api/ERC.Structures.html ================================================  Namespace ERC.Structures
================================================ FILE: ERC/docs/api/ERC.ThreadInfo.html ================================================  Class ThreadInfo
================================================ FILE: ERC/docs/api/ERC.Utilities.Convert.html ================================================  Class Convert
================================================ FILE: ERC/docs/api/ERC.Utilities.OpcodeAssembler.html ================================================  Class OpcodeAssembler
================================================ FILE: ERC/docs/api/ERC.Utilities.OpcodeDisassembler.html ================================================  Class OpcodeDisassembler
================================================ FILE: ERC/docs/api/ERC.Utilities.PatternTools.html ================================================  Class PatternTools
================================================ FILE: ERC/docs/api/ERC.Utilities.Payloads.html ================================================  Class Payloads
================================================ FILE: ERC/docs/api/ERC.Utilities.PtrRemover.html ================================================  Class PtrRemover
================================================ FILE: ERC/docs/api/ERC.Utilities.RopChainGenerator32.X86Lists.html ================================================  Class RopChainGenerator32.X86Lists
================================================ FILE: ERC/docs/api/ERC.Utilities.RopChainGenerator32.html ================================================  Class RopChainGenerator32
================================================ FILE: ERC/docs/api/ERC.Utilities.RopChainGenerator64.X64Lists.html ================================================  Class RopChainGenerator64.X64Lists
================================================ FILE: ERC/docs/api/ERC.Utilities.RopChainGenerator64.html ================================================  Class RopChainGenerator64
================================================ FILE: ERC/docs/api/ERC.Utilities.html ================================================  Namespace ERC.Utilities
================================================ FILE: ERC/docs/api/ERC.html ================================================  Namespace ERC
================================================ FILE: ERC/docs/api/index.html ================================================  ERC.Net
================================================ FILE: ERC/docs/api/toc.html ================================================  ================================================ FILE: ERC/docs/articles/LICENSE.html ================================================ 
================================================ FILE: ERC/docs/articles/intro.html ================================================  ERC.Net
================================================ FILE: ERC/docs/articles/toc.html ================================================  ================================================ FILE: ERC/docs/index.html ================================================  ERC.Net API Documentation.
================================================ FILE: ERC/docs/manifest.json ================================================ { "homepages": [], "source_base_path": "C:/Users/tester/Documents/GitHub/ERC.net/docs", "xrefmap": "xrefmap.yml", "files": [ { "type": "ManagedReference", "source_relative_path": "api/ERC.DisplayOutput.yml", "output": { ".html": { "relative_path": "api/ERC.DisplayOutput.html", "hash": "uSYzKJoVWETKQVnHYkipvA==" } }, "is_incremental": false, "version": "" }, { "type": "ManagedReference", "source_relative_path": "api/ERC.ERCException.yml", "output": { ".html": { "relative_path": "api/ERC.ERCException.html", "hash": "N9DFx+jCIZ1kehMpnWEwfA==" } }, "is_incremental": false, "version": "" }, { "type": "ManagedReference", "source_relative_path": "api/ERC.ErcCore.yml", "output": { ".html": { "relative_path": "api/ERC.ErcCore.html", "hash": "9IZRrvUxvz8k3i52PlpDpg==" } }, "is_incremental": false, "version": "" }, { "type": "ManagedReference", "source_relative_path": "api/ERC.ErcResult-1.yml", "output": { ".html": { "relative_path": "api/ERC.ErcResult-1.html", "hash": "WYfQ8G5E2EhB5JyUiEsovw==" } }, "is_incremental": false, "version": "" }, { "type": "ManagedReference", "source_relative_path": "api/ERC.MachineType.yml", "output": { ".html": { "relative_path": "api/ERC.MachineType.html", "hash": "5yfM5V9gEwgoY9gz5QPOQQ==" } }, "is_incremental": false, "version": "" }, { "type": "ManagedReference", "source_relative_path": "api/ERC.ModuleInfo.yml", "output": { ".html": { "relative_path": "api/ERC.ModuleInfo.html", "hash": "9C6u6oFxGZw0ci6TbvgVeQ==" } }, "is_incremental": false, "version": "" }, { "type": "ManagedReference", "source_relative_path": "api/ERC.ProcessInfo.yml", "output": { ".html": { "relative_path": "api/ERC.ProcessInfo.html", "hash": "sKVlzd+yWeL3BNm4lpEUrA==" } }, "is_incremental": false, "version": "" }, { "type": "ManagedReference", "source_relative_path": "api/ERC.Structures.AllocationProtect.yml", "output": { ".html": { "relative_path": "api/ERC.Structures.AllocationProtect.html", "hash": "cGNnldFfQKV3EK5eVwymSA==" } }, "is_incremental": false, "version": "" }, { "type": "ManagedReference", "source_relative_path": "api/ERC.Structures.CONTEXT32.yml", "output": { ".html": { "relative_path": "api/ERC.Structures.CONTEXT32.html", "hash": "RwgCozxQlmS3GhwBd3Dw3A==" } }, "is_incremental": false, "version": "" }, { "type": "ManagedReference", "source_relative_path": "api/ERC.Structures.CONTEXT64.yml", "output": { ".html": { "relative_path": "api/ERC.Structures.CONTEXT64.html", "hash": "2NsD4+XIMA5EUY/Jub3HOA==" } }, "is_incremental": false, "version": "" }, { "type": "ManagedReference", "source_relative_path": "api/ERC.Structures.CONTEXT_FLAGS.yml", "output": { ".html": { "relative_path": "api/ERC.Structures.CONTEXT_FLAGS.html", "hash": "KgT2JGr7eSSKweXru6j5wA==" } }, "is_incremental": false, "version": "" }, { "type": "ManagedReference", "source_relative_path": "api/ERC.Structures.ClientID.yml", "output": { ".html": { "relative_path": "api/ERC.Structures.ClientID.html", "hash": "LICOYcjp530Ezdg3hoKggg==" } }, "is_incremental": false, "version": "" }, { "type": "ManagedReference", "source_relative_path": "api/ERC.Structures.FLOATING_SAVE_AREA.yml", "output": { ".html": { "relative_path": "api/ERC.Structures.FLOATING_SAVE_AREA.html", "hash": "c8d30/NNm1Zc4R1V5QfceA==" } }, "is_incremental": false, "version": "" }, { "type": "ManagedReference", "source_relative_path": "api/ERC.Structures.IMAGE_DATA_DIRECTORY.yml", "output": { ".html": { "relative_path": "api/ERC.Structures.IMAGE_DATA_DIRECTORY.html", "hash": "wjHXN/VAzWbAwXwaZPPzkg==" } }, "is_incremental": false, "version": "" }, { "type": "ManagedReference", "source_relative_path": "api/ERC.Structures.IMAGE_DOS_HEADER.yml", "output": { ".html": { "relative_path": "api/ERC.Structures.IMAGE_DOS_HEADER.html", "hash": "GZ3UjpuCuEu5QP0JV5r5pA==" } }, "is_incremental": false, "version": "" }, { "type": "ManagedReference", "source_relative_path": "api/ERC.Structures.IMAGE_FILE_HEADER.yml", "output": { ".html": { "relative_path": "api/ERC.Structures.IMAGE_FILE_HEADER.html", "hash": "Bwj5+Vi2cwjmpfezQIeWJw==" } }, "is_incremental": false, "version": "" }, { "type": "ManagedReference", "source_relative_path": "api/ERC.Structures.IMAGE_LOAD_CONFIG_CODE_INTEGRITY.yml", "output": { ".html": { "relative_path": "api/ERC.Structures.IMAGE_LOAD_CONFIG_CODE_INTEGRITY.html", "hash": "IZw6dOI0kjGT/rIgZyyJ+w==" } }, "is_incremental": false, "version": "" }, { "type": "ManagedReference", "source_relative_path": "api/ERC.Structures.IMAGE_LOAD_CONFIG_DIRECTORY32.yml", "output": { ".html": { "relative_path": "api/ERC.Structures.IMAGE_LOAD_CONFIG_DIRECTORY32.html", "hash": "SRGb8SqJeShOcFFp754wHA==" } }, "is_incremental": false, "version": "" }, { "type": "ManagedReference", "source_relative_path": "api/ERC.Structures.IMAGE_LOAD_CONFIG_DIRECTORY64.yml", "output": { ".html": { "relative_path": "api/ERC.Structures.IMAGE_LOAD_CONFIG_DIRECTORY64.html", "hash": "4HNcZ+eu0Azhr++sqzkwgg==" } }, "is_incremental": false, "version": "" }, { "type": "ManagedReference", "source_relative_path": "api/ERC.Structures.IMAGE_NT_HEADERS32.yml", "output": { ".html": { "relative_path": "api/ERC.Structures.IMAGE_NT_HEADERS32.html", "hash": "FyBVNZyh6PWAt43ZY1BYXQ==" } }, "is_incremental": false, "version": "" }, { "type": "ManagedReference", "source_relative_path": "api/ERC.Structures.IMAGE_NT_HEADERS64.yml", "output": { ".html": { "relative_path": "api/ERC.Structures.IMAGE_NT_HEADERS64.html", "hash": "DepcbKsMIOw6CTSU8OiQfQ==" } }, "is_incremental": false, "version": "" }, { "type": "ManagedReference", "source_relative_path": "api/ERC.Structures.IMAGE_OPTIONAL_HEADER32.yml", "output": { ".html": { "relative_path": "api/ERC.Structures.IMAGE_OPTIONAL_HEADER32.html", "hash": "l2982mUrRICAzTA40DukpA==" } }, "is_incremental": false, "version": "" }, { "type": "ManagedReference", "source_relative_path": "api/ERC.Structures.IMAGE_OPTIONAL_HEADER64.yml", "output": { ".html": { "relative_path": "api/ERC.Structures.IMAGE_OPTIONAL_HEADER64.html", "hash": "Xvq+aAwnY3GqWPeSqtpwDA==" } }, "is_incremental": false, "version": "" }, { "type": "ManagedReference", "source_relative_path": "api/ERC.Structures.LIST_ENTRY.yml", "output": { ".html": { "relative_path": "api/ERC.Structures.LIST_ENTRY.html", "hash": "VdcJQTRIBfiwnTnAJxVV8Q==" } }, "is_incremental": false, "version": "" }, { "type": "ManagedReference", "source_relative_path": "api/ERC.Structures.LOADED_IMAGE.yml", "output": { ".html": { "relative_path": "api/ERC.Structures.LOADED_IMAGE.html", "hash": "pQKbsgiHvrHqc3Iq4TeFLg==" } }, "is_incremental": false, "version": "" }, { "type": "ManagedReference", "source_relative_path": "api/ERC.Structures.LoadLibraryFlags.yml", "output": { ".html": { "relative_path": "api/ERC.Structures.LoadLibraryFlags.html", "hash": "IohngiHhNws1gH5nfsoVWQ==" } }, "is_incremental": false, "version": "" }, { "type": "ManagedReference", "source_relative_path": "api/ERC.Structures.M128A.yml", "output": { ".html": { "relative_path": "api/ERC.Structures.M128A.html", "hash": "R7e838YgKIj+caDDgHKubQ==" } }, "is_incremental": false, "version": "" }, { "type": "ManagedReference", "source_relative_path": "api/ERC.Structures.MEMORY_BASIC_INFORMATION32.yml", "output": { ".html": { "relative_path": "api/ERC.Structures.MEMORY_BASIC_INFORMATION32.html", "hash": "A1ojjPM1+mn/fBAMSaHiBQ==" } }, "is_incremental": false, "version": "" }, { "type": "ManagedReference", "source_relative_path": "api/ERC.Structures.MEMORY_BASIC_INFORMATION64.yml", "output": { ".html": { "relative_path": "api/ERC.Structures.MEMORY_BASIC_INFORMATION64.html", "hash": "c/+N2Dtz+aT//bhbXa18sQ==" } }, "is_incremental": false, "version": "" }, { "type": "ManagedReference", "source_relative_path": "api/ERC.Structures.MagicType.yml", "output": { ".html": { "relative_path": "api/ERC.Structures.MagicType.html", "hash": "d96xnXpM9r/hRX0WDyZgNg==" } }, "is_incremental": false, "version": "" }, { "type": "ManagedReference", "source_relative_path": "api/ERC.Structures.ProcessAccessFlags.yml", "output": { ".html": { "relative_path": "api/ERC.Structures.ProcessAccessFlags.html", "hash": "GA0ruj9C44NeOQvKji5Ybg==" } }, "is_incremental": false, "version": "" }, { "type": "ManagedReference", "source_relative_path": "api/ERC.Structures.RegisterInfo.yml", "output": { ".html": { "relative_path": "api/ERC.Structures.RegisterInfo.html", "hash": "JJy1/LZFychjeoNs4M0mtg==" } }, "is_incremental": false, "version": "" }, { "type": "ManagedReference", "source_relative_path": "api/ERC.Structures.StateEnum.yml", "output": { ".html": { "relative_path": "api/ERC.Structures.StateEnum.html", "hash": "VKUJ04gDA+xta4zFG33Ngw==" } }, "is_incremental": false, "version": "" }, { "type": "ManagedReference", "source_relative_path": "api/ERC.Structures.SubSystemType.yml", "output": { ".html": { "relative_path": "api/ERC.Structures.SubSystemType.html", "hash": "WgwdwtSTKygAXIy18dedKg==" } }, "is_incremental": false, "version": "" }, { "type": "ManagedReference", "source_relative_path": "api/ERC.Structures.TEB.yml", "output": { ".html": { "relative_path": "api/ERC.Structures.TEB.html", "hash": "K7hd9RXsGYVL+lwdcahYiA==" } }, "is_incremental": false, "version": "" }, { "type": "ManagedReference", "source_relative_path": "api/ERC.Structures.ThreadAccess.yml", "output": { ".html": { "relative_path": "api/ERC.Structures.ThreadAccess.html", "hash": "u/xuZgP1viOxTzL9GLXXFA==" } }, "is_incremental": false, "version": "" }, { "type": "ManagedReference", "source_relative_path": "api/ERC.Structures.ThreadBasicInformation.yml", "output": { ".html": { "relative_path": "api/ERC.Structures.ThreadBasicInformation.html", "hash": "9uMIulB2vsVa+/eeZaG4tw==" } }, "is_incremental": false, "version": "" }, { "type": "ManagedReference", "source_relative_path": "api/ERC.Structures.TypeEnum.yml", "output": { ".html": { "relative_path": "api/ERC.Structures.TypeEnum.html", "hash": "4aV72qOxe2a5ZGTOO4QbvA==" } }, "is_incremental": false, "version": "" }, { "type": "ManagedReference", "source_relative_path": "api/ERC.Structures.XSAVE_FORMAT64.yml", "output": { ".html": { "relative_path": "api/ERC.Structures.XSAVE_FORMAT64.html", "hash": "HGoepyAi3CJHnVPs+v02VQ==" } }, "is_incremental": false, "version": "" }, { "type": "ManagedReference", "source_relative_path": "api/ERC.Structures.yml", "output": { ".html": { "relative_path": "api/ERC.Structures.html", "hash": "ds6+Dm2PmcnglrU7vE7xjQ==" } }, "is_incremental": false, "version": "" }, { "type": "ManagedReference", "source_relative_path": "api/ERC.ThreadInfo.yml", "output": { ".html": { "relative_path": "api/ERC.ThreadInfo.html", "hash": "PcgKJN9nURRIQMgQVYSOSA==" } }, "is_incremental": false, "version": "" }, { "type": "ManagedReference", "source_relative_path": "api/ERC.Utilities.Convert.yml", "output": { ".html": { "relative_path": "api/ERC.Utilities.Convert.html", "hash": "O+EEBM/ljqjnImBqbsfkbg==" } }, "is_incremental": false, "version": "" }, { "type": "ManagedReference", "source_relative_path": "api/ERC.Utilities.OpcodeAssembler.yml", "output": { ".html": { "relative_path": "api/ERC.Utilities.OpcodeAssembler.html", "hash": "eFBIH+zEd50gxvAsFQ9RZQ==" } }, "is_incremental": false, "version": "" }, { "type": "ManagedReference", "source_relative_path": "api/ERC.Utilities.OpcodeDisassembler.yml", "output": { ".html": { "relative_path": "api/ERC.Utilities.OpcodeDisassembler.html", "hash": "vSj1IFUSrpSh0ndWo8k03Q==" } }, "is_incremental": false, "version": "" }, { "type": "ManagedReference", "source_relative_path": "api/ERC.Utilities.PatternTools.yml", "output": { ".html": { "relative_path": "api/ERC.Utilities.PatternTools.html", "hash": "YxTA14LQM1CWI+JouDRrGw==" } }, "is_incremental": false, "version": "" }, { "type": "ManagedReference", "source_relative_path": "api/ERC.Utilities.Payloads.yml", "output": { ".html": { "relative_path": "api/ERC.Utilities.Payloads.html", "hash": "phx0gCfYMmHTD0P6T9tS/Q==" } }, "is_incremental": false, "version": "" }, { "type": "ManagedReference", "source_relative_path": "api/ERC.Utilities.PtrRemover.yml", "output": { ".html": { "relative_path": "api/ERC.Utilities.PtrRemover.html", "hash": "GdQqodlX3mYCNIbnWreviA==" } }, "is_incremental": false, "version": "" }, { "type": "ManagedReference", "source_relative_path": "api/ERC.Utilities.RopChainGenerator32.X86Lists.yml", "output": { ".html": { "relative_path": "api/ERC.Utilities.RopChainGenerator32.X86Lists.html", "hash": "U8cfWwlJmyWJTD2gG4Jp7A==" } }, "is_incremental": false, "version": "" }, { "type": "ManagedReference", "source_relative_path": "api/ERC.Utilities.RopChainGenerator32.yml", "output": { ".html": { "relative_path": "api/ERC.Utilities.RopChainGenerator32.html", "hash": "GCi3SaahGGNOfVZZf7zfEg==" } }, "is_incremental": false, "version": "" }, { "type": "ManagedReference", "source_relative_path": "api/ERC.Utilities.RopChainGenerator64.X64Lists.yml", "output": { ".html": { "relative_path": "api/ERC.Utilities.RopChainGenerator64.X64Lists.html", "hash": "W3s053W0r4+bcZWgRh3hZA==" } }, "is_incremental": false, "version": "" }, { "type": "ManagedReference", "source_relative_path": "api/ERC.Utilities.RopChainGenerator64.yml", "output": { ".html": { "relative_path": "api/ERC.Utilities.RopChainGenerator64.html", "hash": "Reqw0yjmak/1eo4nM+x75Q==" } }, "is_incremental": false, "version": "" }, { "type": "ManagedReference", "source_relative_path": "api/ERC.Utilities.yml", "output": { ".html": { "relative_path": "api/ERC.Utilities.html", "hash": "l9f45qJY/Tf5QvxzOAUGsw==" } }, "is_incremental": false, "version": "" }, { "type": "ManagedReference", "source_relative_path": "api/ERC.yml", "output": { ".html": { "relative_path": "api/ERC.html", "hash": "KZSG7RbnbE5JO6i9YQhQJg==" } }, "is_incremental": false, "version": "" }, { "type": "Conceptual", "source_relative_path": "api/index.md", "output": { ".html": { "relative_path": "api/index.html", "hash": "hPYCWqYUEXVZVL3qVrcZ+g==" } }, "is_incremental": false, "version": "" }, { "type": "Toc", "source_relative_path": "api/toc.yml", "output": { ".html": { "relative_path": "api/toc.html", "hash": "HWdu7b5uaUb2KaI1afXOqQ==" } }, "is_incremental": false, "version": "" }, { "type": "Conceptual", "source_relative_path": "articles/LICENSE.md", "output": { ".html": { "relative_path": "articles/LICENSE.html", "hash": "eCZ6/K0A4mKe6kRRZan5+A==" } }, "is_incremental": false, "version": "" }, { "type": "Conceptual", "source_relative_path": "articles/intro.md", "output": { ".html": { "relative_path": "articles/intro.html", "hash": "VX1ZJ6Es1l7iI9bmpxoOrw==" } }, "is_incremental": false, "version": "" }, { "type": "Toc", "source_relative_path": "articles/toc.yml", "output": { ".html": { "relative_path": "articles/toc.html", "hash": "gB8AESyvNru97tzIZofEEg==" } }, "is_incremental": false, "version": "" }, { "type": "Conceptual", "source_relative_path": "index.md", "output": { ".html": { "relative_path": "index.html", "hash": "5a++662pB3tOEugXxQ/cvQ==" } }, "is_incremental": false, "version": "" }, { "type": "Toc", "source_relative_path": "toc.yml", "output": { ".html": { "relative_path": "toc.html", "hash": "+rHUkRZHZRi5gd1aTU6lJA==" } }, "is_incremental": false, "version": "" } ], "incremental_info": [ { "status": { "can_incremental": false, "details": "Cannot build incrementally because last build info is missing.", "incrementalPhase": "build", "total_file_count": 0, "skipped_file_count": 0, "full_build_reason_code": "NoAvailableBuildCache" }, "processors": { "ConceptualDocumentProcessor": { "can_incremental": false, "incrementalPhase": "build", "total_file_count": 4, "skipped_file_count": 0 }, "ManagedReferenceDocumentProcessor": { "can_incremental": false, "incrementalPhase": "build", "total_file_count": 53, "skipped_file_count": 0 }, "TocDocumentProcessor": { "can_incremental": false, "details": "Processor TocDocumentProcessor cannot support incremental build because the processor doesn't implement ISupportIncrementalDocumentProcessor interface.", "incrementalPhase": "build", "total_file_count": 0, "skipped_file_count": 0 } } }, { "status": { "can_incremental": false, "details": "Cannot support incremental post processing, the reason is: last post processor info is null.", "incrementalPhase": "postProcessing", "total_file_count": 0, "skipped_file_count": 0 }, "processors": {} } ], "version_info": {}, "groups": [ { "xrefmap": "xrefmap.yml" } ] } ================================================ FILE: ERC/docs/search-stopwords.json ================================================ [ "a", "able", "about", "across", "after", "all", "almost", "also", "am", "among", "an", "and", "any", "are", "as", "at", "be", "because", "been", "but", "by", "can", "cannot", "could", "dear", "did", "do", "does", "either", "else", "ever", "every", "for", "from", "get", "got", "had", "has", "have", "he", "her", "hers", "him", "his", "how", "however", "i", "if", "in", "into", "is", "it", "its", "just", "least", "let", "like", "likely", "may", "me", "might", "most", "must", "my", "neither", "no", "nor", "not", "of", "off", "often", "on", "only", "or", "other", "our", "own", "rather", "said", "say", "says", "she", "should", "since", "so", "some", "than", "that", "the", "their", "them", "then", "there", "these", "they", "this", "tis", "to", "too", "twas", "us", "wants", "was", "we", "were", "what", "when", "where", "which", "while", "who", "whom", "why", "will", "with", "would", "yet", "you", "your" ] ================================================ FILE: ERC/docs/styles/docfx.css ================================================ /* Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. */ html, body { font-family: 'Segoe UI', Tahoma, Helvetica, sans-serif; height: 100%; } button, a { color: #337ab7; cursor: pointer; } button:hover, button:focus, a:hover, a:focus { color: #23527c; text-decoration: none; } a.disable, a.disable:hover { text-decoration: none; cursor: default; color: #000000; } h1, h2, h3, h4, h5, h6, .text-break { word-wrap: break-word; word-break: break-word; } h1 mark, h2 mark, h3 mark, h4 mark, h5 mark, h6 mark { padding: 0; } .inheritance .level0:before, .inheritance .level1:before, .inheritance .level2:before, .inheritance .level3:before, .inheritance .level4:before, .inheritance .level5:before { content: '↳'; margin-right: 5px; } .inheritance .level0 { margin-left: 0em; } .inheritance .level1 { margin-left: 1em; } .inheritance .level2 { margin-left: 2em; } .inheritance .level3 { margin-left: 3em; } .inheritance .level4 { margin-left: 4em; } .inheritance .level5 { margin-left: 5em; } span.parametername, span.paramref, span.typeparamref { font-style: italic; } span.languagekeyword{ font-weight: bold; } svg:hover path { fill: #ffffff; } .hljs { display: inline; background-color: inherit; padding: 0; } /* additional spacing fixes */ .btn + .btn { margin-left: 10px; } .btn.pull-right { margin-left: 10px; margin-top: 5px; } .table { margin-bottom: 10px; } table p { margin-bottom: 0; } table a { display: inline-block; } /* Make hidden attribute compatible with old browser.*/ [hidden] { display: none !important; } h1, .h1, h2, .h2, h3, .h3 { margin-top: 15px; margin-bottom: 10px; font-weight: 400; } h4, .h4, h5, .h5, h6, .h6 { margin-top: 10px; margin-bottom: 5px; } .navbar { margin-bottom: 0; } #wrapper { min-height: 100%; position: relative; } /* blends header footer and content together with gradient effect */ .grad-top { /* For Safari 5.1 to 6.0 */ /* For Opera 11.1 to 12.0 */ /* For Firefox 3.6 to 15 */ background: linear-gradient(rgba(0, 0, 0, 0.05), rgba(0, 0, 0, 0)); /* Standard syntax */ height: 5px; } .grad-bottom { /* For Safari 5.1 to 6.0 */ /* For Opera 11.1 to 12.0 */ /* For Firefox 3.6 to 15 */ background: linear-gradient(rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.05)); /* Standard syntax */ height: 5px; } .divider { margin: 0 5px; color: #cccccc; } hr { border-color: #cccccc; } header { position: fixed; top: 0; left: 0; right: 0; z-index: 1000; } header .navbar { border-width: 0 0 1px; border-radius: 0; } .navbar-brand { font-size: inherit; padding: 0; } .navbar-collapse { margin: 0 -15px; } .subnav { min-height: 40px; } .inheritance h5, .inheritedMembers h5{ padding-bottom: 5px; border-bottom: 1px solid #ccc; } article h1, article h2, article h3, article h4{ margin-top: 25px; } article h4{ border-bottom: 1px solid #ccc; } article span.small.pull-right{ margin-top: 20px; } article section { margin-left: 1em; } /*.expand-all { padding: 10px 0; }*/ .breadcrumb { margin: 0; padding: 10px 0; background-color: inherit; white-space: nowrap; } .breadcrumb > li + li:before { content: "\00a0/"; } #autocollapse.collapsed .navbar-header { float: none; } #autocollapse.collapsed .navbar-toggle { display: block; } #autocollapse.collapsed .navbar-collapse { border-top: 1px solid transparent; box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1); } #autocollapse.collapsed .navbar-collapse.collapse { display: none !important; } #autocollapse.collapsed .navbar-nav { float: none !important; margin: 7.5px -15px; } #autocollapse.collapsed .navbar-nav > li { float: none; } #autocollapse.collapsed .navbar-nav > li > a { padding-top: 10px; padding-bottom: 10px; } #autocollapse.collapsed .collapse.in, #autocollapse.collapsed .collapsing { display: block !important; } #autocollapse.collapsed .collapse.in .navbar-right, #autocollapse.collapsed .collapsing .navbar-right { float: none !important; } #autocollapse .form-group { width: 100%; } #autocollapse .form-control { width: 100%; } #autocollapse .navbar-header { margin-left: 0; margin-right: 0; } #autocollapse .navbar-brand { margin-left: 0; } .collapse.in, .collapsing { text-align: center; } .collapsing .navbar-form { margin: 0 auto; max-width: 400px; padding: 10px 15px; box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); } .collapsed .collapse.in .navbar-form { margin: 0 auto; max-width: 400px; padding: 10px 15px; box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); } .navbar .navbar-nav { display: inline-block; } .docs-search { background: white; vertical-align: middle; } .docs-search > .search-query { font-size: 14px; border: 0; width: 120%; color: #555; } .docs-search > .search-query:focus { outline: 0; } .search-results-frame { clear: both; display: table; width: 100%; } .search-results.ng-hide { display: none; } .search-results-container { padding-bottom: 1em; border-top: 1px solid #111; background: rgba(25, 25, 25, 0.5); } .search-results-container .search-results-group { padding-top: 50px !important; padding: 10px; } .search-results-group-heading { font-family: "Open Sans"; padding-left: 10px; color: white; } .search-close { position: absolute; left: 50%; margin-left: -100px; color: white; text-align: center; padding: 5px; background: #333; border-top-right-radius: 5px; border-top-left-radius: 5px; width: 200px; box-shadow: 0 0 10px #111; } #search { display: none; } /* Search results display*/ #search-results { max-width: 960px !important; margin-top: 120px; margin-bottom: 115px; margin-left: auto; margin-right: auto; line-height: 1.8; display: none; } #search-results>.search-list { text-align: center; font-size: 2.5rem; margin-bottom: 50px; } #search-results p { text-align: center; } #search-results p .index-loading { animation: index-loading 1.5s infinite linear; -webkit-animation: index-loading 1.5s infinite linear; -o-animation: index-loading 1.5s infinite linear; font-size: 2.5rem; } @keyframes index-loading { from { transform: scale(1) rotate(0deg);} to { transform: scale(1) rotate(360deg);} } @-webkit-keyframes index-loading { from { -webkit-transform: rotate(0deg);} to { -webkit-transform: rotate(360deg);} } @-o-keyframes index-loading { from { -o-transform: rotate(0deg);} to { -o-transform: rotate(360deg);} } #search-results .sr-items { font-size: 24px; } .sr-item { margin-bottom: 25px; } .sr-item>.item-href { font-size: 14px; color: #093; } .sr-item>.item-brief { font-size: 13px; } .pagination>li>a { color: #47A7A0 } .pagination>.active>a { background-color: #47A7A0; border-color: #47A7A0; } .fixed_header { position: fixed; width: 100%; padding-bottom: 10px; padding-top: 10px; margin: 0px; top: 0; z-index: 9999; left: 0; } .fixed_header+.toc{ margin-top: 50px; margin-left: 0; } .sidenav, .fixed_header, .toc { background-color: #f1f1f1; } .sidetoc { position: fixed; width: 260px; top: 150px; bottom: 0; overflow-x: hidden; overflow-y: auto; background-color: #f1f1f1; border-left: 1px solid #e7e7e7; border-right: 1px solid #e7e7e7; z-index: 1; } .sidetoc.shiftup { bottom: 70px; } body .toc{ background-color: #f1f1f1; overflow-x: hidden; } .sidetoggle.ng-hide { display: block !important; } .sidetoc-expand > .caret { margin-left: 0px; margin-top: -2px; } .sidetoc-expand > .caret-side { border-left: 4px solid; border-top: 4px solid transparent; border-bottom: 4px solid transparent; margin-left: 4px; margin-top: -4px; } .sidetoc-heading { font-weight: 500; } .toc { margin: 0px 0 0 10px; padding: 0 10px; } .expand-stub { position: absolute; left: -10px; } .toc .nav > li > a.sidetoc-expand { position: absolute; top: 0; left: 0; } .toc .nav > li > a { color: #666666; margin-left: 5px; display: block; padding: 0; } .toc .nav > li > a:hover, .toc .nav > li > a:focus { color: #000000; background: none; text-decoration: inherit; } .toc .nav > li.active > a { color: #337ab7; } .toc .nav > li.active > a:hover, .toc .nav > li.active > a:focus { color: #23527c; } .toc .nav > li> .expand-stub { cursor: pointer; } .toc .nav > li.active > .expand-stub::before, .toc .nav > li.in > .expand-stub::before, .toc .nav > li.in.active > .expand-stub::before, .toc .nav > li.filtered > .expand-stub::before { content: "-"; } .toc .nav > li > .expand-stub::before, .toc .nav > li.active > .expand-stub::before { content: "+"; } .toc .nav > li.filtered > ul, .toc .nav > li.in > ul { display: block; } .toc .nav > li > ul { display: none; } .toc ul{ font-size: 12px; margin: 0 0 0 3px; } .toc .level1 > li { font-weight: bold; margin-top: 10px; position: relative; font-size: 16px; } .toc .level2 { font-weight: normal; margin: 5px 0 0 15px; font-size: 14px; } .toc-toggle { display: none; margin: 0 15px 0px 15px; } .sidefilter { position: fixed; top: 90px; width: 260px; background-color: #f1f1f1; padding: 15px; border-left: 1px solid #e7e7e7; border-right: 1px solid #e7e7e7; z-index: 1; } .toc-filter { border-radius: 5px; background: #fff; color: #666666; padding: 5px; position: relative; margin: 0 5px 0 5px; } .toc-filter > input { border: 0; color: #666666; padding-left: 20px; padding-right: 20px; width: 100%; } .toc-filter > input:focus { outline: 0; } .toc-filter > .filter-icon { position: absolute; top: 10px; left: 5px; } .toc-filter > .clear-icon { position: absolute; top: 10px; right: 5px; } .article { margin-top: 120px; margin-bottom: 115px; } #_content>a{ margin-top: 105px; } .article.grid-right { margin-left: 280px; } .inheritance hr { margin-top: 5px; margin-bottom: 5px; } .article img { max-width: 100%; } .sideaffix { margin-top: 50px; font-size: 12px; max-height: 100%; overflow: hidden; top: 100px; bottom: 10px; position: fixed; } .sideaffix.shiftup { bottom: 70px; } .affix { position: relative; height: 100%; } .sideaffix > div.contribution { margin-bottom: 20px; } .sideaffix > div.contribution > ul > li > a.contribution-link { padding: 6px 10px; font-weight: bold; font-size: 14px; } .sideaffix > div.contribution > ul > li > a.contribution-link:hover { background-color: #ffffff; } .sideaffix ul.nav > li > a:focus { background: none; } .affix h5 { font-weight: bold; text-transform: uppercase; padding-left: 10px; font-size: 12px; } .affix > ul.level1 { overflow: hidden; padding-bottom: 10px; height: calc(100% - 100px); } .affix ul > li > a:before { color: #cccccc; position: absolute; } .affix ul > li > a:hover { background: none; color: #666666; } .affix ul > li.active > a, .affix ul > li.active > a:before { color: #337ab7; } .affix ul > li > a { padding: 5px 12px; color: #666666; } .affix > ul > li.active:last-child { margin-bottom: 50px; } .affix > ul > li > a:before { content: "|"; font-size: 16px; top: 1px; left: 0; } .affix > ul > li.active > a, .affix > ul > li.active > a:before { color: #337ab7; font-weight: bold; } .affix ul ul > li > a { padding: 2px 15px; } .affix ul ul > li > a:before { content: ">"; font-size: 14px; top: -1px; left: 5px; } .affix ul > li > a:before, .affix ul ul { display: none; } .affix ul > li.active > ul, .affix ul > li.active > a:before, .affix ul > li > a:hover:before { display: block; white-space: nowrap; } .codewrapper { position: relative; } .trydiv { height: 0px; } .tryspan { position: absolute; top: 0px; right: 0px; border-style: solid; border-radius: 0px 4px; box-sizing: border-box; border-width: 1px; border-color: #cccccc; text-align: center; padding: 2px 8px; background-color: white; font-size: 12px; cursor: pointer; z-index: 100; display: none; color: #767676; } .tryspan:hover { background-color: #3b8bd0; color: white; border-color: #3b8bd0; } .codewrapper:hover .tryspan { display: block; } .sample-response .response-content{ max-height: 200px; } footer { position: absolute; left: 0; right: 0; bottom: 0; z-index: 1000; } .footer { border-top: 1px solid #e7e7e7; background-color: #f8f8f8; padding: 15px 0; } @media (min-width: 768px) { #sidetoggle.collapse { display: block; } .topnav .navbar-nav { float: none; white-space: nowrap; } .topnav .navbar-nav > li { float: none; display: inline-block; } } @media only screen and (max-width: 768px) { #mobile-indicator { display: block; } /* TOC display for responsive */ .article { margin-top: 30px !important; } header { position: static; } .topnav { text-align: center; } .sidenav { padding: 15px 0; margin-left: -15px; margin-right: -15px; } .sidefilter { position: static; width: auto; float: none; border: none; } .sidetoc { position: static; width: auto; float: none; padding-bottom: 0px; border: none; } .toc .nav > li, .toc .nav > li >a { display: inline-block; } .toc li:after { margin-left: -3px; margin-right: 5px; content: ", "; color: #666666; } .toc .level1 > li { display: block; } .toc .level1 > li:after { display: none; } .article.grid-right { margin-left: 0; } .grad-top, .grad-bottom { display: none; } .toc-toggle { display: block; } .sidetoggle.ng-hide { display: none !important; } /*.expand-all { display: none; }*/ .sideaffix { display: none; } .mobile-hide { display: none; } .breadcrumb { white-space: inherit; } /* workaround for #hashtag url is no longer needed*/ h1:before, h2:before, h3:before, h4:before { content: ''; display: none; } } /* For toc iframe */ @media (max-width: 260px) { .toc .level2 > li { display: block; } .toc .level2 > li:after { display: none; } } /* For code snippet line highlight */ pre > code .line-highlight { background-color: #ffffcc; } /* Alerts */ .alert h5 { text-transform: uppercase; font-weight: bold; margin-top: 0; } .alert h5:before { position:relative; top:1px; display:inline-block; font-family:'Glyphicons Halflings'; line-height:1; -webkit-font-smoothing:antialiased; -moz-osx-font-smoothing:grayscale; margin-right: 5px; font-weight: normal; } .alert-info h5:before { content:"\e086" } .alert-warning h5:before { content:"\e127" } .alert-danger h5:before { content:"\e107" } /* For Embedded Video */ div.embeddedvideo { padding-top: 56.25%; position: relative; width: 100%; } div.embeddedvideo iframe { position: absolute; top: 0; left: 0; right: 0; bottom: 0; width: 100%; height: 100%; } /* For printer */ @media print{ .article.grid-right { margin-top: 0px; margin-left: 0px; } .sideaffix { display: none; } .mobile-hide { display: none; } .footer { display: none; } } /* For tabbed content */ .tabGroup { margin-top: 1rem; } .tabGroup ul[role="tablist"] { margin: 0; padding: 0; list-style: none; } .tabGroup ul[role="tablist"] > li { list-style: none; display: inline-block; } .tabGroup a[role="tab"] { color: #6e6e6e; box-sizing: border-box; display: inline-block; padding: 5px 7.5px; text-decoration: none; border-bottom: 2px solid #fff; } .tabGroup a[role="tab"]:hover, .tabGroup a[role="tab"]:focus, .tabGroup a[role="tab"][aria-selected="true"] { border-bottom: 2px solid #0050C5; } .tabGroup a[role="tab"][aria-selected="true"] { color: #222; } .tabGroup a[role="tab"]:hover, .tabGroup a[role="tab"]:focus { color: #0050C5; } .tabGroup a[role="tab"]:focus { outline: 1px solid #0050C5; outline-offset: -1px; } @media (min-width: 768px) { .tabGroup a[role="tab"] { padding: 5px 15px; } } .tabGroup section[role="tabpanel"] { border: 1px solid #e0e0e0; padding: 15px; margin: 0; overflow: hidden; } .tabGroup section[role="tabpanel"] > .codeHeader, .tabGroup section[role="tabpanel"] > pre { margin-left: -16px; margin-right: -16px; } .tabGroup section[role="tabpanel"] > :first-child { margin-top: 0; } .tabGroup section[role="tabpanel"] > pre:last-child { display: block; margin-bottom: -16px; } .mainContainer[dir='rtl'] main ul[role="tablist"] { margin: 0; } ================================================ FILE: ERC/docs/styles/docfx.js ================================================ // Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See LICENSE file in the project root for full license information. $(function () { var active = 'active'; var expanded = 'in'; var collapsed = 'collapsed'; var filtered = 'filtered'; var show = 'show'; var hide = 'hide'; var util = new utility(); workAroundFixedHeaderForAnchors(); highlight(); enableSearch(); renderTables(); renderAlerts(); renderLinks(); renderNavbar(); renderSidebar(); renderAffix(); renderFooter(); renderLogo(); breakText(); renderTabs(); window.refresh = function (article) { // Update markup result if (typeof article == 'undefined' || typeof article.content == 'undefined') console.error("Null Argument"); $("article.content").html(article.content); highlight(); renderTables(); renderAlerts(); renderAffix(); renderTabs(); } // Add this event listener when needed // window.addEventListener('content-update', contentUpdate); function breakText() { $(".xref").addClass("text-break"); var texts = $(".text-break"); texts.each(function () { $(this).breakWord(); }); } // Styling for tables in conceptual documents using Bootstrap. // See http://getbootstrap.com/css/#tables function renderTables() { $('table').addClass('table table-bordered table-striped table-condensed').wrap('
'); } // Styling for alerts. function renderAlerts() { $('.NOTE, .TIP').addClass('alert alert-info'); $('.WARNING').addClass('alert alert-warning'); $('.IMPORTANT, .CAUTION').addClass('alert alert-danger'); } // Enable anchors for headings. (function () { anchors.options = { placement: 'left', visible: 'touch' }; anchors.add('article h2:not(.no-anchor), article h3:not(.no-anchor), article h4:not(.no-anchor)'); })(); // Open links to different host in a new window. function renderLinks() { if ($("meta[property='docfx:newtab']").attr("content") === "true") { $(document.links).filter(function () { return this.hostname !== window.location.hostname; }).attr('target', '_blank'); } } // Enable highlight.js function highlight() { $('pre code').each(function (i, block) { hljs.highlightBlock(block); }); $('pre code[highlight-lines]').each(function (i, block) { if (block.innerHTML === "") return; var lines = block.innerHTML.split('\n'); queryString = block.getAttribute('highlight-lines'); if (!queryString) return; var ranges = queryString.split(','); for (var j = 0, range; range = ranges[j++];) { var found = range.match(/^(\d+)\-(\d+)?$/); if (found) { // consider region as `{startlinenumber}-{endlinenumber}`, in which {endlinenumber} is optional var start = +found[1]; var end = +found[2]; if (isNaN(end) || end > lines.length) { end = lines.length; } } else { // consider region as a sigine line number if (isNaN(range)) continue; var start = +range; var end = start; } if (start <= 0 || end <= 0 || start > end || start > lines.length) { // skip current region if invalid continue; } lines[start - 1] = '' + lines[start - 1]; lines[end - 1] = lines[end - 1] + ''; } block.innerHTML = lines.join('\n'); }); } // Support full-text-search function enableSearch() { var query; var relHref = $("meta[property='docfx\\:rel']").attr("content"); if (typeof relHref === 'undefined') { return; } try { var worker = new Worker(relHref + 'styles/search-worker.js'); if (!worker && !window.worker) { localSearch(); } else { webWorkerSearch(); } renderSearchBox(); highlightKeywords(); addSearchEvent(); } catch (e) { console.error(e); } //Adjust the position of search box in navbar function renderSearchBox() { autoCollapse(); $(window).on('resize', autoCollapse); $(document).on('click', '.navbar-collapse.in', function (e) { if ($(e.target).is('a')) { $(this).collapse('hide'); } }); function autoCollapse() { var navbar = $('#autocollapse'); if (navbar.height() === null) { setTimeout(autoCollapse, 300); } navbar.removeClass(collapsed); if (navbar.height() > 60) { navbar.addClass(collapsed); } } } // Search factory function localSearch() { console.log("using local search"); var lunrIndex = lunr(function () { this.ref('href'); this.field('title', { boost: 50 }); this.field('keywords', { boost: 20 }); }); lunr.tokenizer.seperator = /[\s\-\.]+/; var searchData = {}; var searchDataRequest = new XMLHttpRequest(); var indexPath = relHref + "index.json"; if (indexPath) { searchDataRequest.open('GET', indexPath); searchDataRequest.onload = function () { if (this.status != 200) { return; } searchData = JSON.parse(this.responseText); for (var prop in searchData) { if (searchData.hasOwnProperty(prop)) { lunrIndex.add(searchData[prop]); } } } searchDataRequest.send(); } $("body").bind("queryReady", function () { var hits = lunrIndex.search(query); var results = []; hits.forEach(function (hit) { var item = searchData[hit.ref]; results.push({ 'href': item.href, 'title': item.title, 'keywords': item.keywords }); }); handleSearchResults(results); }); } function webWorkerSearch() { console.log("using Web Worker"); var indexReady = $.Deferred(); worker.onmessage = function (oEvent) { switch (oEvent.data.e) { case 'index-ready': indexReady.resolve(); break; case 'query-ready': var hits = oEvent.data.d; handleSearchResults(hits); break; } } indexReady.promise().done(function () { $("body").bind("queryReady", function () { worker.postMessage({ q: query }); }); if (query && (query.length >= 3)) { worker.postMessage({ q: query }); } }); } // Highlight the searching keywords function highlightKeywords() { var q = url('?q'); if (q !== null) { var keywords = q.split("%20"); keywords.forEach(function (keyword) { if (keyword !== "") { $('.data-searchable *').mark(keyword); $('article *').mark(keyword); } }); } } function addSearchEvent() { $('body').bind("searchEvent", function () { $('#search-query').keypress(function (e) { return e.which !== 13; }); $('#search-query').keyup(function () { query = $(this).val(); if (query.length < 3) { flipContents("show"); } else { flipContents("hide"); $("body").trigger("queryReady"); $('#search-results>.search-list').text('Search Results for "' + query + '"'); } }).off("keydown"); }); } function flipContents(action) { if (action === "show") { $('.hide-when-search').show(); $('#search-results').hide(); } else { $('.hide-when-search').hide(); $('#search-results').show(); } } function relativeUrlToAbsoluteUrl(currentUrl, relativeUrl) { var currentItems = currentUrl.split(/\/+/); var relativeItems = relativeUrl.split(/\/+/); var depth = currentItems.length - 1; var items = []; for (var i = 0; i < relativeItems.length; i++) { if (relativeItems[i] === '..') { depth--; } else if (relativeItems[i] !== '.') { items.push(relativeItems[i]); } } return currentItems.slice(0, depth).concat(items).join('/'); } function extractContentBrief(content) { var briefOffset = 512; var words = query.split(/\s+/g); var queryIndex = content.indexOf(words[0]); var briefContent; if (queryIndex > briefOffset) { return "..." + content.slice(queryIndex - briefOffset, queryIndex + briefOffset) + "..."; } else if (queryIndex <= briefOffset) { return content.slice(0, queryIndex + briefOffset) + "..."; } } function handleSearchResults(hits) { var numPerPage = 10; $('#pagination').empty(); $('#pagination').removeData("twbs-pagination"); if (hits.length === 0) { $('#search-results>.sr-items').html('

No results found

'); } else { $('#pagination').twbsPagination({ totalPages: Math.ceil(hits.length / numPerPage), visiblePages: 5, onPageClick: function (event, page) { var start = (page - 1) * numPerPage; var curHits = hits.slice(start, start + numPerPage); $('#search-results>.sr-items').empty().append( curHits.map(function (hit) { var currentUrl = window.location.href; var itemRawHref = relativeUrlToAbsoluteUrl(currentUrl, relHref + hit.href); var itemHref = relHref + hit.href + "?q=" + query; var itemTitle = hit.title; var itemBrief = extractContentBrief(hit.keywords); var itemNode = $('
').attr('class', 'sr-item'); var itemTitleNode = $('
').attr('class', 'item-title').append($('').attr('href', itemHref).attr("target", "_blank").text(itemTitle)); var itemHrefNode = $('
').attr('class', 'item-href').text(itemRawHref); var itemBriefNode = $('
').attr('class', 'item-brief').text(itemBrief); itemNode.append(itemTitleNode).append(itemHrefNode).append(itemBriefNode); return itemNode; }) ); query.split(/\s+/).forEach(function (word) { if (word !== '') { $('#search-results>.sr-items *').mark(word); } }); } }); } } }; // Update href in navbar function renderNavbar() { var navbar = $('#navbar ul')[0]; if (typeof (navbar) === 'undefined') { loadNavbar(); } else { $('#navbar ul a.active').parents('li').addClass(active); renderBreadcrumb(); showSearch(); } function showSearch() { if ($('#search-results').length !== 0) { $('#search').show(); $('body').trigger("searchEvent"); } } function loadNavbar() { var navbarPath = $("meta[property='docfx\\:navrel']").attr("content"); if (!navbarPath) { return; } navbarPath = navbarPath.replace(/\\/g, '/'); var tocPath = $("meta[property='docfx\\:tocrel']").attr("content") || ''; if (tocPath) tocPath = tocPath.replace(/\\/g, '/'); $.get(navbarPath, function (data) { $(data).find("#toc>ul").appendTo("#navbar"); showSearch(); var index = navbarPath.lastIndexOf('/'); var navrel = ''; if (index > -1) { navrel = navbarPath.substr(0, index + 1); } $('#navbar>ul').addClass('navbar-nav'); var currentAbsPath = util.getAbsolutePath(window.location.pathname); // set active item $('#navbar').find('a[href]').each(function (i, e) { var href = $(e).attr("href"); if (util.isRelativePath(href)) { href = navrel + href; $(e).attr("href", href); var isActive = false; var originalHref = e.name; if (originalHref) { originalHref = navrel + originalHref; if (util.getDirectory(util.getAbsolutePath(originalHref)) === util.getDirectory(util.getAbsolutePath(tocPath))) { isActive = true; } } else { if (util.getAbsolutePath(href) === currentAbsPath) { var dropdown = $(e).attr('data-toggle') == "dropdown" if (!dropdown) { isActive = true; } } } if (isActive) { $(e).addClass(active); } } }); renderNavbar(); }); } } function renderSidebar() { var sidetoc = $('#sidetoggle .sidetoc')[0]; if (typeof (sidetoc) === 'undefined') { loadToc(); } else { registerTocEvents(); if ($('footer').is(':visible')) { $('.sidetoc').addClass('shiftup'); } // Scroll to active item var top = 0; $('#toc a.active').parents('li').each(function (i, e) { $(e).addClass(active).addClass(expanded); $(e).children('a').addClass(active); top += $(e).position().top; }) $('.sidetoc').scrollTop(top - 50); if ($('footer').is(':visible')) { $('.sidetoc').addClass('shiftup'); } renderBreadcrumb(); } function registerTocEvents() { var tocFilterInput = $('#toc_filter_input'); var tocFilterClearButton = $('#toc_filter_clear'); $('.toc .nav > li > .expand-stub').click(function (e) { $(e.target).parent().toggleClass(expanded); }); $('.toc .nav > li > .expand-stub + a:not([href])').click(function (e) { $(e.target).parent().toggleClass(expanded); }); tocFilterInput.on('input', function (e) { var val = this.value; //Save filter string to local session storage if (typeof(Storage) !== "undefined") { sessionStorage.filterString = val; } if (val === '') { // Clear 'filtered' class $('#toc li').removeClass(filtered).removeClass(hide); tocFilterClearButton.fadeOut(); return; } tocFilterClearButton.fadeIn(); // set all parent nodes status $('#toc li>a').filter(function (i, e) { return $(e).siblings().length > 0 }).each(function (i, anchor) { var parent = $(anchor).parent(); parent.addClass(hide); parent.removeClass(show); parent.removeClass(filtered); }) // Get leaf nodes $('#toc li>a').filter(function (i, e) { return $(e).siblings().length === 0 }).each(function (i, anchor) { var text = $(anchor).attr('title'); var parent = $(anchor).parent(); var parentNodes = parent.parents('ul>li'); for (var i = 0; i < parentNodes.length; i++) { var parentText = $(parentNodes[i]).children('a').attr('title'); if (parentText) text = parentText + '.' + text; }; if (filterNavItem(text, val)) { parent.addClass(show); parent.removeClass(hide); } else { parent.addClass(hide); parent.removeClass(show); } }); $('#toc li>a').filter(function (i, e) { return $(e).siblings().length > 0 }).each(function (i, anchor) { var parent = $(anchor).parent(); if (parent.find('li.show').length > 0) { parent.addClass(show); parent.addClass(filtered); parent.removeClass(hide); } else { parent.addClass(hide); parent.removeClass(show); parent.removeClass(filtered); } }) function filterNavItem(name, text) { if (!text) return true; if (name && name.toLowerCase().indexOf(text.toLowerCase()) > -1) return true; return false; } }); // toc filter clear button tocFilterClearButton.hide(); tocFilterClearButton.on("click", function(e){ tocFilterInput.val(""); tocFilterInput.trigger('input'); if (typeof(Storage) !== "undefined") { sessionStorage.filterString = ""; } }); //Set toc filter from local session storage on page load if (typeof(Storage) !== "undefined") { tocFilterInput.val(sessionStorage.filterString); tocFilterInput.trigger('input'); } } function loadToc() { var tocPath = $("meta[property='docfx\\:tocrel']").attr("content"); if (!tocPath) { return; } tocPath = tocPath.replace(/\\/g, '/'); $('#sidetoc').load(tocPath + " #sidetoggle > div", function () { var index = tocPath.lastIndexOf('/'); var tocrel = ''; if (index > -1) { tocrel = tocPath.substr(0, index + 1); } var currentHref = util.getAbsolutePath(window.location.pathname); $('#sidetoc').find('a[href]').each(function (i, e) { var href = $(e).attr("href"); if (util.isRelativePath(href)) { href = tocrel + href; $(e).attr("href", href); } if (util.getAbsolutePath(e.href) === currentHref) { $(e).addClass(active); } $(e).breakWord(); }); renderSidebar(); }); } } function renderBreadcrumb() { var breadcrumb = []; $('#navbar a.active').each(function (i, e) { breadcrumb.push({ href: e.href, name: e.innerHTML }); }) $('#toc a.active').each(function (i, e) { breadcrumb.push({ href: e.href, name: e.innerHTML }); }) var html = util.formList(breadcrumb, 'breadcrumb'); $('#breadcrumb').html(html); } //Setup Affix function renderAffix() { var hierarchy = getHierarchy(); if (hierarchy && hierarchy.length > 0) { var html = '
In This Article
' html += util.formList(hierarchy, ['nav', 'bs-docs-sidenav']); $("#affix").empty().append(html); if ($('footer').is(':visible')) { $(".sideaffix").css("bottom", "70px"); } $('#affix a').click(function(e) { var scrollspy = $('[data-spy="scroll"]').data()['bs.scrollspy']; var target = e.target.hash; if (scrollspy && target) { scrollspy.activate(target); } }); } function getHierarchy() { // supported headers are h1, h2, h3, and h4 var $headers = $($.map(['h1', 'h2', 'h3', 'h4'], function (h) { return ".article article " + h; }).join(", ")); // a stack of hierarchy items that are currently being built var stack = []; $headers.each(function (i, e) { if (!e.id) { return; } var item = { name: htmlEncode($(e).text()), href: "#" + e.id, items: [] }; if (!stack.length) { stack.push({ type: e.tagName, siblings: [item] }); return; } var frame = stack[stack.length - 1]; if (e.tagName === frame.type) { frame.siblings.push(item); } else if (e.tagName[1] > frame.type[1]) { // we are looking at a child of the last element of frame.siblings. // push a frame onto the stack. After we've finished building this item's children, // we'll attach it as a child of the last element stack.push({ type: e.tagName, siblings: [item] }); } else { // e.tagName[1] < frame.type[1] // we are looking at a sibling of an ancestor of the current item. // pop frames from the stack, building items as we go, until we reach the correct level at which to attach this item. while (e.tagName[1] < stack[stack.length - 1].type[1]) { buildParent(); } if (e.tagName === stack[stack.length - 1].type) { stack[stack.length - 1].siblings.push(item); } else { stack.push({ type: e.tagName, siblings: [item] }); } } }); while (stack.length > 1) { buildParent(); } function buildParent() { var childrenToAttach = stack.pop(); var parentFrame = stack[stack.length - 1]; var parent = parentFrame.siblings[parentFrame.siblings.length - 1]; $.each(childrenToAttach.siblings, function (i, child) { parent.items.push(child); }); } if (stack.length > 0) { var topLevel = stack.pop().siblings; if (topLevel.length === 1) { // if there's only one topmost header, dump it return topLevel[0].items; } return topLevel; } return undefined; } function htmlEncode(str) { if (!str) return str; return str .replace(/&/g, '&') .replace(/"/g, '"') .replace(/'/g, ''') .replace(//g, '>'); } function htmlDecode(value) { if (!str) return str; return value .replace(/"/g, '"') .replace(/'/g, "'") .replace(/</g, '<') .replace(/>/g, '>') .replace(/&/g, '&'); } function cssEscape(str) { // see: http://stackoverflow.com/questions/2786538/need-to-escape-a-special-character-in-a-jquery-selector-string#answer-2837646 if (!str) return str; return str .replace(/[!"#$%&'()*+,.\/:;<=>?@[\\\]^`{|}~]/g, "\\$&"); } } // Show footer function renderFooter() { initFooter(); $(window).on("scroll", showFooterCore); function initFooter() { if (needFooter()) { shiftUpBottomCss(); $("footer").show(); } else { resetBottomCss(); $("footer").hide(); } } function showFooterCore() { if (needFooter()) { shiftUpBottomCss(); $("footer").fadeIn(); } else { resetBottomCss(); $("footer").fadeOut(); } } function needFooter() { var scrollHeight = $(document).height(); var scrollPosition = $(window).height() + $(window).scrollTop(); return (scrollHeight - scrollPosition) < 1; } function resetBottomCss() { $(".sidetoc").removeClass("shiftup"); $(".sideaffix").removeClass("shiftup"); } function shiftUpBottomCss() { $(".sidetoc").addClass("shiftup"); $(".sideaffix").addClass("shiftup"); } } function renderLogo() { // For LOGO SVG // Replace SVG with inline SVG // http://stackoverflow.com/questions/11978995/how-to-change-color-of-svg-image-using-css-jquery-svg-image-replacement jQuery('img.svg').each(function () { var $img = jQuery(this); var imgID = $img.attr('id'); var imgClass = $img.attr('class'); var imgURL = $img.attr('src'); jQuery.get(imgURL, function (data) { // Get the SVG tag, ignore the rest var $svg = jQuery(data).find('svg'); // Add replaced image's ID to the new SVG if (typeof imgID !== 'undefined') { $svg = $svg.attr('id', imgID); } // Add replaced image's classes to the new SVG if (typeof imgClass !== 'undefined') { $svg = $svg.attr('class', imgClass + ' replaced-svg'); } // Remove any invalid XML tags as per http://validator.w3.org $svg = $svg.removeAttr('xmlns:a'); // Replace image with new SVG $img.replaceWith($svg); }, 'xml'); }); } function renderTabs() { var contentAttrs = { id: 'data-bi-id', name: 'data-bi-name', type: 'data-bi-type' }; var Tab = (function () { function Tab(li, a, section) { this.li = li; this.a = a; this.section = section; } Object.defineProperty(Tab.prototype, "tabIds", { get: function () { return this.a.getAttribute('data-tab').split(' '); }, enumerable: true, configurable: true }); Object.defineProperty(Tab.prototype, "condition", { get: function () { return this.a.getAttribute('data-condition'); }, enumerable: true, configurable: true }); Object.defineProperty(Tab.prototype, "visible", { get: function () { return !this.li.hasAttribute('hidden'); }, set: function (value) { if (value) { this.li.removeAttribute('hidden'); this.li.removeAttribute('aria-hidden'); } else { this.li.setAttribute('hidden', 'hidden'); this.li.setAttribute('aria-hidden', 'true'); } }, enumerable: true, configurable: true }); Object.defineProperty(Tab.prototype, "selected", { get: function () { return !this.section.hasAttribute('hidden'); }, set: function (value) { if (value) { this.a.setAttribute('aria-selected', 'true'); this.a.tabIndex = 0; this.section.removeAttribute('hidden'); this.section.removeAttribute('aria-hidden'); } else { this.a.setAttribute('aria-selected', 'false'); this.a.tabIndex = -1; this.section.setAttribute('hidden', 'hidden'); this.section.setAttribute('aria-hidden', 'true'); } }, enumerable: true, configurable: true }); Tab.prototype.focus = function () { this.a.focus(); }; return Tab; }()); initTabs(document.body); function initTabs(container) { var queryStringTabs = readTabsQueryStringParam(); var elements = container.querySelectorAll('.tabGroup'); var state = { groups: [], selectedTabs: [] }; for (var i = 0; i < elements.length; i++) { var group = initTabGroup(elements.item(i)); if (!group.independent) { updateVisibilityAndSelection(group, state); state.groups.push(group); } } container.addEventListener('click', function (event) { return handleClick(event, state); }); if (state.groups.length === 0) { return state; } selectTabs(queryStringTabs, container); updateTabsQueryStringParam(state); notifyContentUpdated(); return state; } function initTabGroup(element) { var group = { independent: element.hasAttribute('data-tab-group-independent'), tabs: [] }; var li = element.firstElementChild.firstElementChild; while (li) { var a = li.firstElementChild; a.setAttribute(contentAttrs.name, 'tab'); var dataTab = a.getAttribute('data-tab').replace(/\+/g, ' '); a.setAttribute('data-tab', dataTab); var section = element.querySelector("[id=\"" + a.getAttribute('aria-controls') + "\"]"); var tab = new Tab(li, a, section); group.tabs.push(tab); li = li.nextElementSibling; } element.setAttribute(contentAttrs.name, 'tab-group'); element.tabGroup = group; return group; } function updateVisibilityAndSelection(group, state) { var anySelected = false; var firstVisibleTab; for (var _i = 0, _a = group.tabs; _i < _a.length; _i++) { var tab = _a[_i]; tab.visible = tab.condition === null || state.selectedTabs.indexOf(tab.condition) !== -1; if (tab.visible) { if (!firstVisibleTab) { firstVisibleTab = tab; } } tab.selected = tab.visible && arraysIntersect(state.selectedTabs, tab.tabIds); anySelected = anySelected || tab.selected; } if (!anySelected) { for (var _b = 0, _c = group.tabs; _b < _c.length; _b++) { var tabIds = _c[_b].tabIds; for (var _d = 0, tabIds_1 = tabIds; _d < tabIds_1.length; _d++) { var tabId = tabIds_1[_d]; var index = state.selectedTabs.indexOf(tabId); if (index === -1) { continue; } state.selectedTabs.splice(index, 1); } } var tab = firstVisibleTab; tab.selected = true; state.selectedTabs.push(tab.tabIds[0]); } } function getTabInfoFromEvent(event) { if (!(event.target instanceof HTMLElement)) { return null; } var anchor = event.target.closest('a[data-tab]'); if (anchor === null) { return null; } var tabIds = anchor.getAttribute('data-tab').split(' '); var group = anchor.parentElement.parentElement.parentElement.tabGroup; if (group === undefined) { return null; } return { tabIds: tabIds, group: group, anchor: anchor }; } function handleClick(event, state) { var info = getTabInfoFromEvent(event); if (info === null) { return; } event.preventDefault(); info.anchor.href = 'javascript:'; setTimeout(function () { return info.anchor.href = '#' + info.anchor.getAttribute('aria-controls'); }); var tabIds = info.tabIds, group = info.group; var originalTop = info.anchor.getBoundingClientRect().top; if (group.independent) { for (var _i = 0, _a = group.tabs; _i < _a.length; _i++) { var tab = _a[_i]; tab.selected = arraysIntersect(tab.tabIds, tabIds); } } else { if (arraysIntersect(state.selectedTabs, tabIds)) { return; } var previousTabId = group.tabs.filter(function (t) { return t.selected; })[0].tabIds[0]; state.selectedTabs.splice(state.selectedTabs.indexOf(previousTabId), 1, tabIds[0]); for (var _b = 0, _c = state.groups; _b < _c.length; _b++) { var group_1 = _c[_b]; updateVisibilityAndSelection(group_1, state); } updateTabsQueryStringParam(state); } notifyContentUpdated(); var top = info.anchor.getBoundingClientRect().top; if (top !== originalTop && event instanceof MouseEvent) { window.scrollTo(0, window.pageYOffset + top - originalTop); } } function selectTabs(tabIds) { for (var _i = 0, tabIds_1 = tabIds; _i < tabIds_1.length; _i++) { var tabId = tabIds_1[_i]; var a = document.querySelector(".tabGroup > ul > li > a[data-tab=\"" + tabId + "\"]:not([hidden])"); if (a === null) { return; } a.dispatchEvent(new CustomEvent('click', { bubbles: true })); } } function readTabsQueryStringParam() { var qs = parseQueryString(); var t = qs.tabs; if (t === undefined || t === '') { return []; } return t.split(','); } function updateTabsQueryStringParam(state) { var qs = parseQueryString(); qs.tabs = state.selectedTabs.join(); var url = location.protocol + "//" + location.host + location.pathname + "?" + toQueryString(qs) + location.hash; if (location.href === url) { return; } history.replaceState({}, document.title, url); } function toQueryString(args) { var parts = []; for (var name_1 in args) { if (args.hasOwnProperty(name_1) && args[name_1] !== '' && args[name_1] !== null && args[name_1] !== undefined) { parts.push(encodeURIComponent(name_1) + '=' + encodeURIComponent(args[name_1])); } } return parts.join('&'); } function parseQueryString(queryString) { var match; var pl = /\+/g; var search = /([^&=]+)=?([^&]*)/g; var decode = function (s) { return decodeURIComponent(s.replace(pl, ' ')); }; if (queryString === undefined) { queryString = ''; } queryString = queryString.substring(1); var urlParams = {}; while (match = search.exec(queryString)) { urlParams[decode(match[1])] = decode(match[2]); } return urlParams; } function arraysIntersect(a, b) { for (var _i = 0, a_1 = a; _i < a_1.length; _i++) { var itemA = a_1[_i]; for (var _a = 0, b_1 = b; _a < b_1.length; _a++) { var itemB = b_1[_a]; if (itemA === itemB) { return true; } } } return false; } function notifyContentUpdated() { // Dispatch this event when needed // window.dispatchEvent(new CustomEvent('content-update')); } } function utility() { this.getAbsolutePath = getAbsolutePath; this.isRelativePath = isRelativePath; this.isAbsolutePath = isAbsolutePath; this.getDirectory = getDirectory; this.formList = formList; function getAbsolutePath(href) { // Use anchor to normalize href var anchor = $('
')[0]; // Ignore protocal, remove search and query return anchor.host + anchor.pathname; } function isRelativePath(href) { if (href === undefined || href === '' || href[0] === '/') { return false; } return !isAbsolutePath(href); } function isAbsolutePath(href) { return (/^(?:[a-z]+:)?\/\//i).test(href); } function getDirectory(href) { if (!href) return ''; var index = href.lastIndexOf('/'); if (index == -1) return ''; if (index > -1) { return href.substr(0, index); } } function formList(item, classes) { var level = 1; var model = { items: item }; var cls = [].concat(classes).join(" "); return getList(model, cls); function getList(model, cls) { if (!model || !model.items) return null; var l = model.items.length; if (l === 0) return null; var html = '
    '; level++; for (var i = 0; i < l; i++) { var item = model.items[i]; var href = item.href; var name = item.name; if (!name) continue; html += href ? '
  • ' + name + '' : '
  • ' + name; html += getList(item, cls) || ''; html += '
  • '; } html += '
'; return html; } } /** * Add into long word. * @param {String} text - The word to break. It should be in plain text without HTML tags. */ function breakPlainText(text) { if (!text) return text; return text.replace(/([a-z])([A-Z])|(\.)(\w)/g, '$1$3$2$4') } /** * Add into long word. The jQuery element should contain no html tags. * If the jQuery element contains tags, this function will not change the element. */ $.fn.breakWord = function () { if (this.html() == this.text()) { this.html(function (index, text) { return breakPlainText(text); }) } return this; } } // adjusted from https://stackoverflow.com/a/13067009/1523776 function workAroundFixedHeaderForAnchors() { var HISTORY_SUPPORT = !!(history && history.pushState); var ANCHOR_REGEX = /^#[^ ]+$/; function getFixedOffset() { return $('header').first().height(); } /** * If the provided href is an anchor which resolves to an element on the * page, scroll to it. * @param {String} href * @return {Boolean} - Was the href an anchor. */ function scrollIfAnchor(href, pushToHistory) { var match, rect, anchorOffset; if (!ANCHOR_REGEX.test(href)) { return false; } match = document.getElementById(href.slice(1)); if (match) { rect = match.getBoundingClientRect(); anchorOffset = window.pageYOffset + rect.top - getFixedOffset(); window.scrollTo(window.pageXOffset, anchorOffset); // Add the state to history as-per normal anchor links if (HISTORY_SUPPORT && pushToHistory) { history.pushState({}, document.title, location.pathname + href); } } return !!match; } /** * Attempt to scroll to the current location's hash. */ function scrollToCurrent() { scrollIfAnchor(window.location.hash); } /** * If the click event's target was an anchor, fix the scroll position. */ function delegateAnchors(e) { var elem = e.target; if (scrollIfAnchor(elem.getAttribute('href'), true)) { e.preventDefault(); } } $(window).on('hashchange', scrollToCurrent); $(window).load(function () { // scroll to the anchor if present, offset by the header scrollToCurrent(); }); $(document).ready(function () { // Exclude tabbed content case $('a:not([data-tab])').click(function (e) { delegateAnchors(e); }); }); } }); ================================================ FILE: ERC/docs/styles/docfx.vendor.css ================================================ /*! * Bootstrap v3.3.7 (http://getbootstrap.com) * Copyright 2011-2016 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) */ /*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */ .label,sub,sup{vertical-align:baseline} hr,img{border:0} body,figure{margin:0} .btn-group>.btn-group,.btn-toolbar .btn,.btn-toolbar .btn-group,.btn-toolbar .input-group,.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9,.dropdown-menu{float:left} .navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse,.pre-scrollable{max-height:340px} html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%} article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block} audio,canvas,progress,video{display:inline-block;vertical-align:baseline} audio:not([controls]){display:none;height:0} [hidden],template{display:none} a{background-color:transparent} a:active,a:hover{outline:0} b,optgroup,strong{font-weight:700} dfn{font-style:italic} h1{margin:.67em 0} mark{color:#000;background:#ff0} sub,sup{position:relative;font-size:75%;line-height:0} sup{top:-.5em} sub{bottom:-.25em} img{vertical-align:middle} svg:not(:root){overflow:hidden} hr{height:0;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box} pre,textarea{overflow:auto} code,kbd,pre,samp{font-size:1em} button,input,optgroup,select,textarea{margin:0;font:inherit;color:inherit} .glyphicon,address{font-style:normal} button{overflow:visible} button,select{text-transform:none} button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer} button[disabled],html input[disabled]{cursor:default} button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0} input[type=checkbox],input[type=radio]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0} input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto} input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none} table{border-spacing:0;border-collapse:collapse} td,th{padding:0} /*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */ @media print{blockquote,img,pre,tr{page-break-inside:avoid} *,:after,:before{color:#000!important;text-shadow:none!important;background:0 0!important;-webkit-box-shadow:none!important;box-shadow:none!important} a,a:visited{text-decoration:underline} a[href]:after{content:" (" attr(href) ")"} abbr[title]:after{content:" (" attr(title) ")"} a[href^="javascript:"]:after,a[href^="#"]:after{content:""} blockquote,pre{border:1px solid #999} thead{display:table-header-group} img{max-width:100%!important} h2,h3,p{orphans:3;widows:3} h2,h3{page-break-after:avoid} .navbar{display:none} .btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important} .label{border:1px solid #000} .table{border-collapse:collapse!important} .table td,.table th{background-color:#fff!important} .table-bordered td,.table-bordered th{border:1px solid #ddd!important} } .dropdown-menu,.modal-content{-webkit-background-clip:padding-box} .btn,.btn-danger.active,.btn-danger:active,.btn-default.active,.btn-default:active,.btn-info.active,.btn-info:active,.btn-primary.active,.btn-primary:active,.btn-warning.active,.btn-warning:active,.btn.active,.btn:active,.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover,.form-control,.navbar-toggle,.open>.dropdown-toggle.btn-danger,.open>.dropdown-toggle.btn-default,.open>.dropdown-toggle.btn-info,.open>.dropdown-toggle.btn-primary,.open>.dropdown-toggle.btn-warning{background-image:none} .img-thumbnail,body{background-color:#fff} @font-face{font-family:'Glyphicons Halflings';src:url(../fonts/glyphicons-halflings-regular.eot);src:url(../fonts/glyphicons-halflings-regular.eot?#iefix) format('embedded-opentype'),url(../fonts/glyphicons-halflings-regular.woff2) format('woff2'),url(../fonts/glyphicons-halflings-regular.woff) format('woff'),url(../fonts/glyphicons-halflings-regular.ttf) format('truetype'),url(../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular) format('svg')} .glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale} .glyphicon-asterisk:before{content:"\002a"} .glyphicon-plus:before{content:"\002b"} .glyphicon-eur:before,.glyphicon-euro:before{content:"\20ac"} .glyphicon-minus:before{content:"\2212"} .glyphicon-cloud:before{content:"\2601"} .glyphicon-envelope:before{content:"\2709"} .glyphicon-pencil:before{content:"\270f"} .glyphicon-glass:before{content:"\e001"} .glyphicon-music:before{content:"\e002"} .glyphicon-search:before{content:"\e003"} .glyphicon-heart:before{content:"\e005"} .glyphicon-star:before{content:"\e006"} .glyphicon-star-empty:before{content:"\e007"} .glyphicon-user:before{content:"\e008"} .glyphicon-film:before{content:"\e009"} .glyphicon-th-large:before{content:"\e010"} .glyphicon-th:before{content:"\e011"} .glyphicon-th-list:before{content:"\e012"} .glyphicon-ok:before{content:"\e013"} .glyphicon-remove:before{content:"\e014"} .glyphicon-zoom-in:before{content:"\e015"} .glyphicon-zoom-out:before{content:"\e016"} .glyphicon-off:before{content:"\e017"} .glyphicon-signal:before{content:"\e018"} .glyphicon-cog:before{content:"\e019"} .glyphicon-trash:before{content:"\e020"} .glyphicon-home:before{content:"\e021"} .glyphicon-file:before{content:"\e022"} .glyphicon-time:before{content:"\e023"} .glyphicon-road:before{content:"\e024"} .glyphicon-download-alt:before{content:"\e025"} .glyphicon-download:before{content:"\e026"} .glyphicon-upload:before{content:"\e027"} .glyphicon-inbox:before{content:"\e028"} .glyphicon-play-circle:before{content:"\e029"} .glyphicon-repeat:before{content:"\e030"} .glyphicon-refresh:before{content:"\e031"} .glyphicon-list-alt:before{content:"\e032"} .glyphicon-lock:before{content:"\e033"} .glyphicon-flag:before{content:"\e034"} .glyphicon-headphones:before{content:"\e035"} .glyphicon-volume-off:before{content:"\e036"} .glyphicon-volume-down:before{content:"\e037"} .glyphicon-volume-up:before{content:"\e038"} .glyphicon-qrcode:before{content:"\e039"} .glyphicon-barcode:before{content:"\e040"} .glyphicon-tag:before{content:"\e041"} .glyphicon-tags:before{content:"\e042"} .glyphicon-book:before{content:"\e043"} .glyphicon-bookmark:before{content:"\e044"} .glyphicon-print:before{content:"\e045"} .glyphicon-camera:before{content:"\e046"} .glyphicon-font:before{content:"\e047"} .glyphicon-bold:before{content:"\e048"} .glyphicon-italic:before{content:"\e049"} .glyphicon-text-height:before{content:"\e050"} .glyphicon-text-width:before{content:"\e051"} .glyphicon-align-left:before{content:"\e052"} .glyphicon-align-center:before{content:"\e053"} .glyphicon-align-right:before{content:"\e054"} .glyphicon-align-justify:before{content:"\e055"} .glyphicon-list:before{content:"\e056"} .glyphicon-indent-left:before{content:"\e057"} .glyphicon-indent-right:before{content:"\e058"} .glyphicon-facetime-video:before{content:"\e059"} .glyphicon-picture:before{content:"\e060"} .glyphicon-map-marker:before{content:"\e062"} .glyphicon-adjust:before{content:"\e063"} .glyphicon-tint:before{content:"\e064"} .glyphicon-edit:before{content:"\e065"} .glyphicon-share:before{content:"\e066"} .glyphicon-check:before{content:"\e067"} .glyphicon-move:before{content:"\e068"} .glyphicon-step-backward:before{content:"\e069"} .glyphicon-fast-backward:before{content:"\e070"} .glyphicon-backward:before{content:"\e071"} .glyphicon-play:before{content:"\e072"} .glyphicon-pause:before{content:"\e073"} .glyphicon-stop:before{content:"\e074"} .glyphicon-forward:before{content:"\e075"} .glyphicon-fast-forward:before{content:"\e076"} .glyphicon-step-forward:before{content:"\e077"} .glyphicon-eject:before{content:"\e078"} .glyphicon-chevron-left:before{content:"\e079"} .glyphicon-chevron-right:before{content:"\e080"} .glyphicon-plus-sign:before{content:"\e081"} .glyphicon-minus-sign:before{content:"\e082"} .glyphicon-remove-sign:before{content:"\e083"} .glyphicon-ok-sign:before{content:"\e084"} .glyphicon-question-sign:before{content:"\e085"} .glyphicon-info-sign:before{content:"\e086"} .glyphicon-screenshot:before{content:"\e087"} .glyphicon-remove-circle:before{content:"\e088"} .glyphicon-ok-circle:before{content:"\e089"} .glyphicon-ban-circle:before{content:"\e090"} .glyphicon-arrow-left:before{content:"\e091"} .glyphicon-arrow-right:before{content:"\e092"} .glyphicon-arrow-up:before{content:"\e093"} .glyphicon-arrow-down:before{content:"\e094"} .glyphicon-share-alt:before{content:"\e095"} .glyphicon-resize-full:before{content:"\e096"} .glyphicon-resize-small:before{content:"\e097"} .glyphicon-exclamation-sign:before{content:"\e101"} .glyphicon-gift:before{content:"\e102"} .glyphicon-leaf:before{content:"\e103"} .glyphicon-fire:before{content:"\e104"} .glyphicon-eye-open:before{content:"\e105"} .glyphicon-eye-close:before{content:"\e106"} .glyphicon-warning-sign:before{content:"\e107"} .glyphicon-plane:before{content:"\e108"} .glyphicon-calendar:before{content:"\e109"} .glyphicon-random:before{content:"\e110"} .glyphicon-comment:before{content:"\e111"} .glyphicon-magnet:before{content:"\e112"} .glyphicon-chevron-up:before{content:"\e113"} .glyphicon-chevron-down:before{content:"\e114"} .glyphicon-retweet:before{content:"\e115"} .glyphicon-shopping-cart:before{content:"\e116"} .glyphicon-folder-close:before{content:"\e117"} .glyphicon-folder-open:before{content:"\e118"} .glyphicon-resize-vertical:before{content:"\e119"} .glyphicon-resize-horizontal:before{content:"\e120"} .glyphicon-hdd:before{content:"\e121"} .glyphicon-bullhorn:before{content:"\e122"} .glyphicon-bell:before{content:"\e123"} .glyphicon-certificate:before{content:"\e124"} .glyphicon-thumbs-up:before{content:"\e125"} .glyphicon-thumbs-down:before{content:"\e126"} .glyphicon-hand-right:before{content:"\e127"} .glyphicon-hand-left:before{content:"\e128"} .glyphicon-hand-up:before{content:"\e129"} .glyphicon-hand-down:before{content:"\e130"} .glyphicon-circle-arrow-right:before{content:"\e131"} .glyphicon-circle-arrow-left:before{content:"\e132"} .glyphicon-circle-arrow-up:before{content:"\e133"} .glyphicon-circle-arrow-down:before{content:"\e134"} .glyphicon-globe:before{content:"\e135"} .glyphicon-wrench:before{content:"\e136"} .glyphicon-tasks:before{content:"\e137"} .glyphicon-filter:before{content:"\e138"} .glyphicon-briefcase:before{content:"\e139"} .glyphicon-fullscreen:before{content:"\e140"} .glyphicon-dashboard:before{content:"\e141"} .glyphicon-paperclip:before{content:"\e142"} .glyphicon-heart-empty:before{content:"\e143"} .glyphicon-link:before{content:"\e144"} .glyphicon-phone:before{content:"\e145"} .glyphicon-pushpin:before{content:"\e146"} .glyphicon-usd:before{content:"\e148"} .glyphicon-gbp:before{content:"\e149"} .glyphicon-sort:before{content:"\e150"} .glyphicon-sort-by-alphabet:before{content:"\e151"} .glyphicon-sort-by-alphabet-alt:before{content:"\e152"} .glyphicon-sort-by-order:before{content:"\e153"} .glyphicon-sort-by-order-alt:before{content:"\e154"} .glyphicon-sort-by-attributes:before{content:"\e155"} .glyphicon-sort-by-attributes-alt:before{content:"\e156"} .glyphicon-unchecked:before{content:"\e157"} .glyphicon-expand:before{content:"\e158"} .glyphicon-collapse-down:before{content:"\e159"} .glyphicon-collapse-up:before{content:"\e160"} .glyphicon-log-in:before{content:"\e161"} .glyphicon-flash:before{content:"\e162"} .glyphicon-log-out:before{content:"\e163"} .glyphicon-new-window:before{content:"\e164"} .glyphicon-record:before{content:"\e165"} .glyphicon-save:before{content:"\e166"} .glyphicon-open:before{content:"\e167"} .glyphicon-saved:before{content:"\e168"} .glyphicon-import:before{content:"\e169"} .glyphicon-export:before{content:"\e170"} .glyphicon-send:before{content:"\e171"} .glyphicon-floppy-disk:before{content:"\e172"} .glyphicon-floppy-saved:before{content:"\e173"} .glyphicon-floppy-remove:before{content:"\e174"} .glyphicon-floppy-save:before{content:"\e175"} .glyphicon-floppy-open:before{content:"\e176"} .glyphicon-credit-card:before{content:"\e177"} .glyphicon-transfer:before{content:"\e178"} .glyphicon-cutlery:before{content:"\e179"} .glyphicon-header:before{content:"\e180"} .glyphicon-compressed:before{content:"\e181"} .glyphicon-earphone:before{content:"\e182"} .glyphicon-phone-alt:before{content:"\e183"} .glyphicon-tower:before{content:"\e184"} .glyphicon-stats:before{content:"\e185"} .glyphicon-sd-video:before{content:"\e186"} .glyphicon-hd-video:before{content:"\e187"} .glyphicon-subtitles:before{content:"\e188"} .glyphicon-sound-stereo:before{content:"\e189"} .glyphicon-sound-dolby:before{content:"\e190"} .glyphicon-sound-5-1:before{content:"\e191"} .glyphicon-sound-6-1:before{content:"\e192"} .glyphicon-sound-7-1:before{content:"\e193"} .glyphicon-copyright-mark:before{content:"\e194"} .glyphicon-registration-mark:before{content:"\e195"} .glyphicon-cloud-download:before{content:"\e197"} .glyphicon-cloud-upload:before{content:"\e198"} .glyphicon-tree-conifer:before{content:"\e199"} .glyphicon-tree-deciduous:before{content:"\e200"} .glyphicon-cd:before{content:"\e201"} .glyphicon-save-file:before{content:"\e202"} .glyphicon-open-file:before{content:"\e203"} .glyphicon-level-up:before{content:"\e204"} .glyphicon-copy:before{content:"\e205"} .glyphicon-paste:before{content:"\e206"} .glyphicon-alert:before{content:"\e209"} .glyphicon-equalizer:before{content:"\e210"} .glyphicon-king:before{content:"\e211"} .glyphicon-queen:before{content:"\e212"} .glyphicon-pawn:before{content:"\e213"} .glyphicon-bishop:before{content:"\e214"} .glyphicon-knight:before{content:"\e215"} .glyphicon-baby-formula:before{content:"\e216"} .glyphicon-tent:before{content:"\26fa"} .glyphicon-blackboard:before{content:"\e218"} .glyphicon-bed:before{content:"\e219"} .glyphicon-apple:before{content:"\f8ff"} .glyphicon-erase:before{content:"\e221"} .glyphicon-hourglass:before{content:"\231b"} .glyphicon-lamp:before{content:"\e223"} .glyphicon-duplicate:before{content:"\e224"} .glyphicon-piggy-bank:before{content:"\e225"} .glyphicon-scissors:before{content:"\e226"} .glyphicon-bitcoin:before,.glyphicon-btc:before,.glyphicon-xbt:before{content:"\e227"} .glyphicon-jpy:before,.glyphicon-yen:before{content:"\00a5"} .glyphicon-rub:before,.glyphicon-ruble:before{content:"\20bd"} .glyphicon-scale:before{content:"\e230"} .glyphicon-ice-lolly:before{content:"\e231"} .glyphicon-ice-lolly-tasted:before{content:"\e232"} .glyphicon-education:before{content:"\e233"} .glyphicon-option-horizontal:before{content:"\e234"} .glyphicon-option-vertical:before{content:"\e235"} .glyphicon-menu-hamburger:before{content:"\e236"} .glyphicon-modal-window:before{content:"\e237"} .glyphicon-oil:before{content:"\e238"} .glyphicon-grain:before{content:"\e239"} .glyphicon-sunglasses:before{content:"\e240"} .glyphicon-text-size:before{content:"\e241"} .glyphicon-text-color:before{content:"\e242"} .glyphicon-text-background:before{content:"\e243"} .glyphicon-object-align-top:before{content:"\e244"} .glyphicon-object-align-bottom:before{content:"\e245"} .glyphicon-object-align-horizontal:before{content:"\e246"} .glyphicon-object-align-left:before{content:"\e247"} .glyphicon-object-align-vertical:before{content:"\e248"} .glyphicon-object-align-right:before{content:"\e249"} .glyphicon-triangle-right:before{content:"\e250"} .glyphicon-triangle-left:before{content:"\e251"} .glyphicon-triangle-bottom:before{content:"\e252"} .glyphicon-triangle-top:before{content:"\e253"} .glyphicon-console:before{content:"\e254"} .glyphicon-superscript:before{content:"\e255"} .glyphicon-subscript:before{content:"\e256"} .glyphicon-menu-left:before{content:"\e257"} .glyphicon-menu-right:before{content:"\e258"} .glyphicon-menu-down:before{content:"\e259"} .glyphicon-menu-up:before{content:"\e260"} *,:after,:before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box} html{font-size:10px;-webkit-tap-highlight-color:transparent} body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333} button,input,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit} a{color:#337ab7;text-decoration:none} a:focus,a:hover{color:#23527c;text-decoration:underline} a:focus{outline:-webkit-focus-ring-color auto 5px;outline-offset:-2px} .carousel-inner>.item>a>img,.carousel-inner>.item>img,.img-responsive,.thumbnail a>img,.thumbnail>img{display:block;max-width:100%;height:auto} .img-rounded{border-radius:6px} .img-thumbnail{display:inline-block;max-width:100%;height:auto;padding:4px;line-height:1.42857143;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out} .img-circle{border-radius:50%} hr{margin-top:20px;margin-bottom:20px;border-top:1px solid #eee} .sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0} .sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto} [role=button]{cursor:pointer} .h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit} .h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-weight:400;line-height:1;color:#777} .h1,.h2,.h3,h1,h2,h3{margin-top:20px;margin-bottom:10px} .h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small{font-size:65%} .h4,.h5,.h6,h4,h5,h6{margin-top:10px;margin-bottom:10px} .h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-size:75%} .h1,h1{font-size:36px} .h2,h2{font-size:30px} .h3,h3{font-size:24px} .h4,h4{font-size:18px} .h5,h5{font-size:14px} .h6,h6{font-size:12px} p{margin:0 0 10px} .lead{margin-bottom:20px;font-size:16px;font-weight:300;line-height:1.4} dt,kbd kbd,label{font-weight:700} address,blockquote .small,blockquote footer,blockquote small,dd,dt,pre{line-height:1.42857143} @media (min-width:768px){.lead{font-size:21px} } .small,small{font-size:85%} .mark,mark{padding:.2em;background-color:#fcf8e3} .list-inline,.list-unstyled{padding-left:0;list-style:none} .text-left{text-align:left} .text-right{text-align:right} .text-center{text-align:center} .text-justify{text-align:justify} .text-nowrap{white-space:nowrap} .text-lowercase{text-transform:lowercase} .text-uppercase{text-transform:uppercase} .text-capitalize{text-transform:capitalize} .text-muted{color:#777} .text-primary{color:#337ab7} a.text-primary:focus,a.text-primary:hover{color:#286090} .text-success{color:#3c763d} a.text-success:focus,a.text-success:hover{color:#2b542c} .text-info{color:#31708f} a.text-info:focus,a.text-info:hover{color:#245269} .text-warning{color:#8a6d3b} a.text-warning:focus,a.text-warning:hover{color:#66512c} .text-danger{color:#a94442} a.text-danger:focus,a.text-danger:hover{color:#843534} .bg-primary{color:#fff;background-color:#337ab7} a.bg-primary:focus,a.bg-primary:hover{background-color:#286090} .bg-success{background-color:#dff0d8} a.bg-success:focus,a.bg-success:hover{background-color:#c1e2b3} .bg-info{background-color:#d9edf7} a.bg-info:focus,a.bg-info:hover{background-color:#afd9ee} .bg-warning{background-color:#fcf8e3} a.bg-warning:focus,a.bg-warning:hover{background-color:#f7ecb5} .bg-danger{background-color:#f2dede} a.bg-danger:focus,a.bg-danger:hover{background-color:#e4b9b9} pre code,table{background-color:transparent} .page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee} dl,ol,ul{margin-top:0} blockquote ol:last-child,blockquote p:last-child,blockquote ul:last-child,ol ol,ol ul,ul ol,ul ul{margin-bottom:0} address,dl{margin-bottom:20px} ol,ul{margin-bottom:10px} .list-inline{margin-left:-5px} .list-inline>li{display:inline-block;padding-right:5px;padding-left:5px} dd{margin-left:0} @media (min-width:768px){.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap} .dl-horizontal dd{margin-left:180px} .container{width:750px} } abbr[data-original-title],abbr[title]{cursor:help;border-bottom:1px dotted #777} .initialism{font-size:90%;text-transform:uppercase} blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee} blockquote .small,blockquote footer,blockquote small{display:block;font-size:80%;color:#777} legend,pre{display:block;color:#333} blockquote .small:before,blockquote footer:before,blockquote small:before{content:'\2014 \00A0'} .blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;text-align:right;border-right:5px solid #eee;border-left:0} code,kbd{padding:2px 4px;font-size:90%} caption,th{text-align:left} .blockquote-reverse .small:before,.blockquote-reverse footer:before,.blockquote-reverse small:before,blockquote.pull-right .small:before,blockquote.pull-right footer:before,blockquote.pull-right small:before{content:''} .blockquote-reverse .small:after,.blockquote-reverse footer:after,.blockquote-reverse small:after,blockquote.pull-right .small:after,blockquote.pull-right footer:after,blockquote.pull-right small:after{content:'\00A0 \2014'} code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace} code{color:#c7254e;background-color:#f9f2f4;border-radius:4px} kbd{color:#fff;background-color:#333;border-radius:3px;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.25);box-shadow:inset 0 -1px 0 rgba(0,0,0,.25)} kbd kbd{padding:0;font-size:100%;-webkit-box-shadow:none;box-shadow:none} pre{padding:9.5px;margin:0 0 10px;font-size:13px;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px} .container,.container-fluid{margin-right:auto;margin-left:auto} pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;border-radius:0} .container,.container-fluid{padding-right:15px;padding-left:15px} .pre-scrollable{overflow-y:scroll} @media (min-width:992px){.container{width:970px} } @media (min-width:1200px){.container{width:1170px} } .row{margin-right:-15px;margin-left:-15px} .col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{position:relative;min-height:1px;padding-right:15px;padding-left:15px} .col-xs-12{width:100%} .col-xs-11{width:91.66666667%} .col-xs-10{width:83.33333333%} .col-xs-9{width:75%} .col-xs-8{width:66.66666667%} .col-xs-7{width:58.33333333%} .col-xs-6{width:50%} .col-xs-5{width:41.66666667%} .col-xs-4{width:33.33333333%} .col-xs-3{width:25%} .col-xs-2{width:16.66666667%} .col-xs-1{width:8.33333333%} .col-xs-pull-12{right:100%} .col-xs-pull-11{right:91.66666667%} .col-xs-pull-10{right:83.33333333%} .col-xs-pull-9{right:75%} .col-xs-pull-8{right:66.66666667%} .col-xs-pull-7{right:58.33333333%} .col-xs-pull-6{right:50%} .col-xs-pull-5{right:41.66666667%} .col-xs-pull-4{right:33.33333333%} .col-xs-pull-3{right:25%} .col-xs-pull-2{right:16.66666667%} .col-xs-pull-1{right:8.33333333%} .col-xs-pull-0{right:auto} .col-xs-push-12{left:100%} .col-xs-push-11{left:91.66666667%} .col-xs-push-10{left:83.33333333%} .col-xs-push-9{left:75%} .col-xs-push-8{left:66.66666667%} .col-xs-push-7{left:58.33333333%} .col-xs-push-6{left:50%} .col-xs-push-5{left:41.66666667%} .col-xs-push-4{left:33.33333333%} .col-xs-push-3{left:25%} .col-xs-push-2{left:16.66666667%} .col-xs-push-1{left:8.33333333%} .col-xs-push-0{left:auto} .col-xs-offset-12{margin-left:100%} .col-xs-offset-11{margin-left:91.66666667%} .col-xs-offset-10{margin-left:83.33333333%} .col-xs-offset-9{margin-left:75%} .col-xs-offset-8{margin-left:66.66666667%} .col-xs-offset-7{margin-left:58.33333333%} .col-xs-offset-6{margin-left:50%} .col-xs-offset-5{margin-left:41.66666667%} .col-xs-offset-4{margin-left:33.33333333%} .col-xs-offset-3{margin-left:25%} .col-xs-offset-2{margin-left:16.66666667%} .col-xs-offset-1{margin-left:8.33333333%} .col-xs-offset-0{margin-left:0} @media (min-width:768px){.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9{float:left} .col-sm-12{width:100%} .col-sm-11{width:91.66666667%} .col-sm-10{width:83.33333333%} .col-sm-9{width:75%} .col-sm-8{width:66.66666667%} .col-sm-7{width:58.33333333%} .col-sm-6{width:50%} .col-sm-5{width:41.66666667%} .col-sm-4{width:33.33333333%} .col-sm-3{width:25%} .col-sm-2{width:16.66666667%} .col-sm-1{width:8.33333333%} .col-sm-pull-12{right:100%} .col-sm-pull-11{right:91.66666667%} .col-sm-pull-10{right:83.33333333%} .col-sm-pull-9{right:75%} .col-sm-pull-8{right:66.66666667%} .col-sm-pull-7{right:58.33333333%} .col-sm-pull-6{right:50%} .col-sm-pull-5{right:41.66666667%} .col-sm-pull-4{right:33.33333333%} .col-sm-pull-3{right:25%} .col-sm-pull-2{right:16.66666667%} .col-sm-pull-1{right:8.33333333%} .col-sm-pull-0{right:auto} .col-sm-push-12{left:100%} .col-sm-push-11{left:91.66666667%} .col-sm-push-10{left:83.33333333%} .col-sm-push-9{left:75%} .col-sm-push-8{left:66.66666667%} .col-sm-push-7{left:58.33333333%} .col-sm-push-6{left:50%} .col-sm-push-5{left:41.66666667%} .col-sm-push-4{left:33.33333333%} .col-sm-push-3{left:25%} .col-sm-push-2{left:16.66666667%} .col-sm-push-1{left:8.33333333%} .col-sm-push-0{left:auto} .col-sm-offset-12{margin-left:100%} .col-sm-offset-11{margin-left:91.66666667%} .col-sm-offset-10{margin-left:83.33333333%} .col-sm-offset-9{margin-left:75%} .col-sm-offset-8{margin-left:66.66666667%} .col-sm-offset-7{margin-left:58.33333333%} .col-sm-offset-6{margin-left:50%} .col-sm-offset-5{margin-left:41.66666667%} .col-sm-offset-4{margin-left:33.33333333%} .col-sm-offset-3{margin-left:25%} .col-sm-offset-2{margin-left:16.66666667%} .col-sm-offset-1{margin-left:8.33333333%} .col-sm-offset-0{margin-left:0} } @media (min-width:992px){.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9{float:left} .col-md-12{width:100%} .col-md-11{width:91.66666667%} .col-md-10{width:83.33333333%} .col-md-9{width:75%} .col-md-8{width:66.66666667%} .col-md-7{width:58.33333333%} .col-md-6{width:50%} .col-md-5{width:41.66666667%} .col-md-4{width:33.33333333%} .col-md-3{width:25%} .col-md-2{width:16.66666667%} .col-md-1{width:8.33333333%} .col-md-pull-12{right:100%} .col-md-pull-11{right:91.66666667%} .col-md-pull-10{right:83.33333333%} .col-md-pull-9{right:75%} .col-md-pull-8{right:66.66666667%} .col-md-pull-7{right:58.33333333%} .col-md-pull-6{right:50%} .col-md-pull-5{right:41.66666667%} .col-md-pull-4{right:33.33333333%} .col-md-pull-3{right:25%} .col-md-pull-2{right:16.66666667%} .col-md-pull-1{right:8.33333333%} .col-md-pull-0{right:auto} .col-md-push-12{left:100%} .col-md-push-11{left:91.66666667%} .col-md-push-10{left:83.33333333%} .col-md-push-9{left:75%} .col-md-push-8{left:66.66666667%} .col-md-push-7{left:58.33333333%} .col-md-push-6{left:50%} .col-md-push-5{left:41.66666667%} .col-md-push-4{left:33.33333333%} .col-md-push-3{left:25%} .col-md-push-2{left:16.66666667%} .col-md-push-1{left:8.33333333%} .col-md-push-0{left:auto} .col-md-offset-12{margin-left:100%} .col-md-offset-11{margin-left:91.66666667%} .col-md-offset-10{margin-left:83.33333333%} .col-md-offset-9{margin-left:75%} .col-md-offset-8{margin-left:66.66666667%} .col-md-offset-7{margin-left:58.33333333%} .col-md-offset-6{margin-left:50%} .col-md-offset-5{margin-left:41.66666667%} .col-md-offset-4{margin-left:33.33333333%} .col-md-offset-3{margin-left:25%} .col-md-offset-2{margin-left:16.66666667%} .col-md-offset-1{margin-left:8.33333333%} .col-md-offset-0{margin-left:0} } @media (min-width:1200px){.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9{float:left} .col-lg-12{width:100%} .col-lg-11{width:91.66666667%} .col-lg-10{width:83.33333333%} .col-lg-9{width:75%} .col-lg-8{width:66.66666667%} .col-lg-7{width:58.33333333%} .col-lg-6{width:50%} .col-lg-5{width:41.66666667%} .col-lg-4{width:33.33333333%} .col-lg-3{width:25%} .col-lg-2{width:16.66666667%} .col-lg-1{width:8.33333333%} .col-lg-pull-12{right:100%} .col-lg-pull-11{right:91.66666667%} .col-lg-pull-10{right:83.33333333%} .col-lg-pull-9{right:75%} .col-lg-pull-8{right:66.66666667%} .col-lg-pull-7{right:58.33333333%} .col-lg-pull-6{right:50%} .col-lg-pull-5{right:41.66666667%} .col-lg-pull-4{right:33.33333333%} .col-lg-pull-3{right:25%} .col-lg-pull-2{right:16.66666667%} .col-lg-pull-1{right:8.33333333%} .col-lg-pull-0{right:auto} .col-lg-push-12{left:100%} .col-lg-push-11{left:91.66666667%} .col-lg-push-10{left:83.33333333%} .col-lg-push-9{left:75%} .col-lg-push-8{left:66.66666667%} .col-lg-push-7{left:58.33333333%} .col-lg-push-6{left:50%} .col-lg-push-5{left:41.66666667%} .col-lg-push-4{left:33.33333333%} .col-lg-push-3{left:25%} .col-lg-push-2{left:16.66666667%} .col-lg-push-1{left:8.33333333%} .col-lg-push-0{left:auto} .col-lg-offset-12{margin-left:100%} .col-lg-offset-11{margin-left:91.66666667%} .col-lg-offset-10{margin-left:83.33333333%} .col-lg-offset-9{margin-left:75%} .col-lg-offset-8{margin-left:66.66666667%} .col-lg-offset-7{margin-left:58.33333333%} .col-lg-offset-6{margin-left:50%} .col-lg-offset-5{margin-left:41.66666667%} .col-lg-offset-4{margin-left:33.33333333%} .col-lg-offset-3{margin-left:25%} .col-lg-offset-2{margin-left:16.66666667%} .col-lg-offset-1{margin-left:8.33333333%} .col-lg-offset-0{margin-left:0} } caption{padding-top:8px;padding-bottom:8px;color:#777} .table{width:100%;max-width:100%;margin-bottom:20px} .table>tbody>tr>td,.table>tbody>tr>th,.table>tfoot>tr>td,.table>tfoot>tr>th,.table>thead>tr>td,.table>thead>tr>th{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #ddd} .table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd} .table>caption+thead>tr:first-child>td,.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>td,.table>thead:first-child>tr:first-child>th{border-top:0} .table>tbody+tbody{border-top:2px solid #ddd} .table .table{background-color:#fff} .table-condensed>tbody>tr>td,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>td,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>thead>tr>th{padding:5px} .table-bordered,.table-bordered>tbody>tr>td,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>td,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border:1px solid #ddd} .table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border-bottom-width:2px} .table-striped>tbody>tr:nth-of-type(odd){background-color:#f9f9f9} .table-hover>tbody>tr:hover,.table>tbody>tr.active>td,.table>tbody>tr.active>th,.table>tbody>tr>td.active,.table>tbody>tr>th.active,.table>tfoot>tr.active>td,.table>tfoot>tr.active>th,.table>tfoot>tr>td.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>thead>tr.active>th,.table>thead>tr>td.active,.table>thead>tr>th.active{background-color:#f5f5f5} table col[class*=col-]{position:static;display:table-column;float:none} table td[class*=col-],table th[class*=col-]{position:static;display:table-cell;float:none} .table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr.active:hover>th,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover{background-color:#e8e8e8} .table>tbody>tr.success>td,.table>tbody>tr.success>th,.table>tbody>tr>td.success,.table>tbody>tr>th.success,.table>tfoot>tr.success>td,.table>tfoot>tr.success>th,.table>tfoot>tr>td.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>thead>tr.success>th,.table>thead>tr>td.success,.table>thead>tr>th.success{background-color:#dff0d8} .table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr.success:hover>th,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover{background-color:#d0e9c6} .table>tbody>tr.info>td,.table>tbody>tr.info>th,.table>tbody>tr>td.info,.table>tbody>tr>th.info,.table>tfoot>tr.info>td,.table>tfoot>tr.info>th,.table>tfoot>tr>td.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>thead>tr.info>th,.table>thead>tr>td.info,.table>thead>tr>th.info{background-color:#d9edf7} .table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr.info:hover>th,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover{background-color:#c4e3f3} .table>tbody>tr.warning>td,.table>tbody>tr.warning>th,.table>tbody>tr>td.warning,.table>tbody>tr>th.warning,.table>tfoot>tr.warning>td,.table>tfoot>tr.warning>th,.table>tfoot>tr>td.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>thead>tr.warning>th,.table>thead>tr>td.warning,.table>thead>tr>th.warning{background-color:#fcf8e3} .table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr.warning:hover>th,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover{background-color:#faf2cc} .table>tbody>tr.danger>td,.table>tbody>tr.danger>th,.table>tbody>tr>td.danger,.table>tbody>tr>th.danger,.table>tfoot>tr.danger>td,.table>tfoot>tr.danger>th,.table>tfoot>tr>td.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>thead>tr.danger>th,.table>thead>tr>td.danger,.table>thead>tr>th.danger{background-color:#f2dede} .table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr.danger:hover>th,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover{background-color:#ebcccc} .table-responsive{min-height:.01%;overflow-x:auto} @media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd} .table-responsive>.table{margin-bottom:0} .table-responsive>.table>tbody>tr>td,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>td,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>thead>tr>th{white-space:nowrap} .table-responsive>.table-bordered{border:0} .table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0} .table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0} .table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0} } fieldset,legend{padding:0;border:0} fieldset{min-width:0;margin:0} legend{width:100%;margin-bottom:20px;font-size:21px;line-height:inherit;border-bottom:1px solid #e5e5e5} label{display:inline-block;max-width:100%;margin-bottom:5px} input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-appearance:none} input[type=checkbox],input[type=radio]{margin:4px 0 0;margin-top:1px\9;line-height:normal} .form-control,output{font-size:14px;line-height:1.42857143;color:#555;display:block} input[type=file]{display:block} input[type=range]{display:block;width:100%} select[multiple],select[size]{height:auto} input[type=file]:focus,input[type=checkbox]:focus,input[type=radio]:focus{outline:-webkit-focus-ring-color auto 5px;outline-offset:-2px} output{padding-top:7px} .form-control{width:100%;height:34px;padding:6px 12px;background-color:#fff;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s} .form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)} .form-control::-moz-placeholder{color:#999;opacity:1} .form-control:-ms-input-placeholder{color:#999} .form-control::-webkit-input-placeholder{color:#999} .has-success .checkbox,.has-success .checkbox-inline,.has-success .control-label,.has-success .form-control-feedback,.has-success .help-block,.has-success .radio,.has-success .radio-inline,.has-success.checkbox label,.has-success.checkbox-inline label,.has-success.radio label,.has-success.radio-inline label{color:#3c763d} .form-control::-ms-expand{background-color:transparent;border:0} .form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{background-color:#eee;opacity:1} .form-control[disabled],fieldset[disabled] .form-control{cursor:not-allowed} textarea.form-control{height:auto} @media screen and (-webkit-min-device-pixel-ratio:0){input[type=date].form-control,input[type=time].form-control,input[type=datetime-local].form-control,input[type=month].form-control{line-height:34px} .input-group-sm input[type=date],.input-group-sm input[type=time],.input-group-sm input[type=datetime-local],.input-group-sm input[type=month],input[type=date].input-sm,input[type=time].input-sm,input[type=datetime-local].input-sm,input[type=month].input-sm{line-height:30px} .input-group-lg input[type=date],.input-group-lg input[type=time],.input-group-lg input[type=datetime-local],.input-group-lg input[type=month],input[type=date].input-lg,input[type=time].input-lg,input[type=datetime-local].input-lg,input[type=month].input-lg{line-height:46px} } .form-group{margin-bottom:15px} .checkbox,.radio{position:relative;display:block;margin-top:10px;margin-bottom:10px} .checkbox label,.radio label{min-height:20px;padding-left:20px;margin-bottom:0;font-weight:400;cursor:pointer} .checkbox input[type=checkbox],.checkbox-inline input[type=checkbox],.radio input[type=radio],.radio-inline input[type=radio]{position:absolute;margin-top:4px\9;margin-left:-20px} .checkbox+.checkbox,.radio+.radio{margin-top:-5px} .checkbox-inline,.radio-inline{position:relative;display:inline-block;padding-left:20px;margin-bottom:0;font-weight:400;vertical-align:middle;cursor:pointer} .checkbox-inline+.checkbox-inline,.radio-inline+.radio-inline{margin-top:0;margin-left:10px} .checkbox-inline.disabled,.checkbox.disabled label,.radio-inline.disabled,.radio.disabled label,fieldset[disabled] .checkbox label,fieldset[disabled] .checkbox-inline,fieldset[disabled] .radio label,fieldset[disabled] .radio-inline,fieldset[disabled] input[type=checkbox],fieldset[disabled] input[type=radio],input[type=checkbox].disabled,input[type=checkbox][disabled],input[type=radio].disabled,input[type=radio][disabled]{cursor:not-allowed} .form-control-static{min-height:34px;padding-top:7px;padding-bottom:7px;margin-bottom:0} .form-control-static.input-lg,.form-control-static.input-sm{padding-right:0;padding-left:0} .form-group-sm .form-control,.input-sm{padding:5px 10px;border-radius:3px;font-size:12px} .input-sm{height:30px;line-height:1.5} select.input-sm{height:30px;line-height:30px} select[multiple].input-sm,textarea.input-sm{height:auto} .form-group-sm .form-control{height:30px;line-height:1.5} .form-group-lg .form-control,.input-lg{border-radius:6px;padding:10px 16px;font-size:18px} .form-group-sm select.form-control{height:30px;line-height:30px} .form-group-sm select[multiple].form-control,.form-group-sm textarea.form-control{height:auto} .form-group-sm .form-control-static{height:30px;min-height:32px;padding:6px 10px;font-size:12px;line-height:1.5} .input-lg{height:46px;line-height:1.3333333} select.input-lg{height:46px;line-height:46px} select[multiple].input-lg,textarea.input-lg{height:auto} .form-group-lg .form-control{height:46px;line-height:1.3333333} .form-group-lg select.form-control{height:46px;line-height:46px} .form-group-lg select[multiple].form-control,.form-group-lg textarea.form-control{height:auto} .form-group-lg .form-control-static{height:46px;min-height:38px;padding:11px 16px;font-size:18px;line-height:1.3333333} .has-feedback{position:relative} .has-feedback .form-control{padding-right:42.5px} .form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:34px;height:34px;line-height:34px;text-align:center;pointer-events:none} .collapsing,.dropdown,.dropup{position:relative} .form-group-lg .form-control+.form-control-feedback,.input-group-lg+.form-control-feedback,.input-lg+.form-control-feedback{width:46px;height:46px;line-height:46px} .form-group-sm .form-control+.form-control-feedback,.input-group-sm+.form-control-feedback,.input-sm+.form-control-feedback{width:30px;height:30px;line-height:30px} .has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)} .has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168} .has-success .input-group-addon{color:#3c763d;background-color:#dff0d8;border-color:#3c763d} .has-warning .checkbox,.has-warning .checkbox-inline,.has-warning .control-label,.has-warning .form-control-feedback,.has-warning .help-block,.has-warning .radio,.has-warning .radio-inline,.has-warning.checkbox label,.has-warning.checkbox-inline label,.has-warning.radio label,.has-warning.radio-inline label{color:#8a6d3b} .has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)} .has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b} .has-warning .input-group-addon{color:#8a6d3b;background-color:#fcf8e3;border-color:#8a6d3b} .has-error .checkbox,.has-error .checkbox-inline,.has-error .control-label,.has-error .form-control-feedback,.has-error .help-block,.has-error .radio,.has-error .radio-inline,.has-error.checkbox label,.has-error.checkbox-inline label,.has-error.radio label,.has-error.radio-inline label{color:#a94442} .has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)} .has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483} .has-error .input-group-addon{color:#a94442;background-color:#f2dede;border-color:#a94442} .has-feedback label~.form-control-feedback{top:25px} .has-feedback label.sr-only~.form-control-feedback{top:0} .help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373} @media (min-width:768px){.form-inline .form-control-static,.form-inline .form-group{display:inline-block} .form-inline .control-label,.form-inline .form-group{margin-bottom:0;vertical-align:middle} .form-inline .form-control{display:inline-block;width:auto;vertical-align:middle} .form-inline .input-group{display:inline-table;vertical-align:middle} .form-inline .input-group .form-control,.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn{width:auto} .form-inline .input-group>.form-control{width:100%} .form-inline .checkbox,.form-inline .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle} .form-inline .checkbox label,.form-inline .radio label{padding-left:0} .form-inline .checkbox input[type=checkbox],.form-inline .radio input[type=radio]{position:relative;margin-left:0} .form-inline .has-feedback .form-control-feedback{top:0} .form-horizontal .control-label{padding-top:7px;margin-bottom:0;text-align:right} } .form-horizontal .checkbox,.form-horizontal .checkbox-inline,.form-horizontal .radio,.form-horizontal .radio-inline{padding-top:7px;margin-top:0;margin-bottom:0} .form-horizontal .checkbox,.form-horizontal .radio{min-height:27px} .form-horizontal .form-group{margin-right:-15px;margin-left:-15px} .form-horizontal .has-feedback .form-control-feedback{right:15px} @media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:11px;font-size:18px} .form-horizontal .form-group-sm .control-label{padding-top:6px;font-size:12px} } .btn{display:inline-block;padding:6px 12px;margin-bottom:0;font-size:14px;font-weight:400;line-height:1.42857143;text-align:center;white-space:nowrap;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;border:1px solid transparent;border-radius:4px} .btn.active.focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn:active:focus,.btn:focus{outline:-webkit-focus-ring-color auto 5px;outline-offset:-2px} .btn.focus,.btn:focus,.btn:hover{color:#333;text-decoration:none} .btn.active,.btn:active{outline:0;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)} .btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none;opacity:.65} a.btn.disabled,fieldset[disabled] a.btn{pointer-events:none} .btn-default{color:#333;background-color:#fff;border-color:#ccc} .btn-default.focus,.btn-default:focus{color:#333;background-color:#e6e6e6;border-color:#8c8c8c} .btn-default.active,.btn-default:active,.btn-default:hover,.open>.dropdown-toggle.btn-default{color:#333;background-color:#e6e6e6;border-color:#adadad} .btn-default.active.focus,.btn-default.active:focus,.btn-default.active:hover,.btn-default:active.focus,.btn-default:active:focus,.btn-default:active:hover,.open>.dropdown-toggle.btn-default.focus,.open>.dropdown-toggle.btn-default:focus,.open>.dropdown-toggle.btn-default:hover{color:#333;background-color:#d4d4d4;border-color:#8c8c8c} .btn-default.disabled.focus,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled].focus,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#fff;border-color:#ccc} .btn-default .badge{color:#fff;background-color:#333} .btn-primary{color:#fff;background-color:#337ab7;border-color:#2e6da4} .btn-primary.focus,.btn-primary:focus{color:#fff;background-color:#286090;border-color:#122b40} .btn-primary.active,.btn-primary:active,.btn-primary:hover,.open>.dropdown-toggle.btn-primary{color:#fff;background-color:#286090;border-color:#204d74} .btn-primary.active.focus,.btn-primary.active:focus,.btn-primary.active:hover,.btn-primary:active.focus,.btn-primary:active:focus,.btn-primary:active:hover,.open>.dropdown-toggle.btn-primary.focus,.open>.dropdown-toggle.btn-primary:focus,.open>.dropdown-toggle.btn-primary:hover{color:#fff;background-color:#204d74;border-color:#122b40} .btn-primary.disabled.focus,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled].focus,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#337ab7;border-color:#2e6da4} .btn-primary .badge{color:#337ab7;background-color:#fff} .btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c} .btn-success.focus,.btn-success:focus{color:#fff;background-color:#449d44;border-color:#255625} .btn-success.active,.btn-success:active,.btn-success:hover,.open>.dropdown-toggle.btn-success{color:#fff;background-color:#449d44;border-color:#398439} .btn-success.active.focus,.btn-success.active:focus,.btn-success.active:hover,.btn-success:active.focus,.btn-success:active:focus,.btn-success:active:hover,.open>.dropdown-toggle.btn-success.focus,.open>.dropdown-toggle.btn-success:focus,.open>.dropdown-toggle.btn-success:hover{color:#fff;background-color:#398439;border-color:#255625} .btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{background-image:none} .btn-success.disabled.focus,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled].focus,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#5cb85c;border-color:#4cae4c} .btn-success .badge{color:#5cb85c;background-color:#fff} .btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da} .btn-info.focus,.btn-info:focus{color:#fff;background-color:#31b0d5;border-color:#1b6d85} .btn-info.active,.btn-info:active,.btn-info:hover,.open>.dropdown-toggle.btn-info{color:#fff;background-color:#31b0d5;border-color:#269abc} .btn-info.active.focus,.btn-info.active:focus,.btn-info.active:hover,.btn-info:active.focus,.btn-info:active:focus,.btn-info:active:hover,.open>.dropdown-toggle.btn-info.focus,.open>.dropdown-toggle.btn-info:focus,.open>.dropdown-toggle.btn-info:hover{color:#fff;background-color:#269abc;border-color:#1b6d85} .btn-info.disabled.focus,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled].focus,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#5bc0de;border-color:#46b8da} .btn-info .badge{color:#5bc0de;background-color:#fff} .btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236} .btn-warning.focus,.btn-warning:focus{color:#fff;background-color:#ec971f;border-color:#985f0d} .btn-warning.active,.btn-warning:active,.btn-warning:hover,.open>.dropdown-toggle.btn-warning{color:#fff;background-color:#ec971f;border-color:#d58512} .btn-warning.active.focus,.btn-warning.active:focus,.btn-warning.active:hover,.btn-warning:active.focus,.btn-warning:active:focus,.btn-warning:active:hover,.open>.dropdown-toggle.btn-warning.focus,.open>.dropdown-toggle.btn-warning:focus,.open>.dropdown-toggle.btn-warning:hover{color:#fff;background-color:#d58512;border-color:#985f0d} .btn-warning.disabled.focus,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled].focus,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#f0ad4e;border-color:#eea236} .btn-warning .badge{color:#f0ad4e;background-color:#fff} .btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a} .btn-danger.focus,.btn-danger:focus{color:#fff;background-color:#c9302c;border-color:#761c19} .btn-danger.active,.btn-danger:active,.btn-danger:hover,.open>.dropdown-toggle.btn-danger{color:#fff;background-color:#c9302c;border-color:#ac2925} .btn-danger.active.focus,.btn-danger.active:focus,.btn-danger.active:hover,.btn-danger:active.focus,.btn-danger:active:focus,.btn-danger:active:hover,.open>.dropdown-toggle.btn-danger.focus,.open>.dropdown-toggle.btn-danger:focus,.open>.dropdown-toggle.btn-danger:hover{color:#fff;background-color:#ac2925;border-color:#761c19} .btn-danger.disabled.focus,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled].focus,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#d9534f;border-color:#d43f3a} .btn-danger .badge{color:#d9534f;background-color:#fff} .btn-link{font-weight:400;color:#337ab7;border-radius:0} .btn-link,.btn-link.active,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none} .btn-link,.btn-link:active,.btn-link:focus,.btn-link:hover{border-color:transparent} .btn-link:focus,.btn-link:hover{color:#23527c;text-decoration:underline;background-color:transparent} .btn-link[disabled]:focus,.btn-link[disabled]:hover,fieldset[disabled] .btn-link:focus,fieldset[disabled] .btn-link:hover{color:#777;text-decoration:none} .btn-group-lg>.btn,.btn-lg{padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px} .btn-group-sm>.btn,.btn-sm{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px} .btn-group-xs>.btn,.btn-xs{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px} .btn-block{display:block;width:100%} .btn-block+.btn-block{margin-top:5px} input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%} .fade{opacity:0;-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear} .fade.in{opacity:1} .collapse{display:none} .collapse.in{display:block} tr.collapse.in{display:table-row} tbody.collapse.in{display:table-row-group} .collapsing{height:0;overflow:hidden;-webkit-transition-timing-function:ease;-o-transition-timing-function:ease;transition-timing-function:ease;-webkit-transition-duration:.35s;-o-transition-duration:.35s;transition-duration:.35s;-webkit-transition-property:height,visibility;-o-transition-property:height,visibility;transition-property:height,visibility} .caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px dashed;border-top:4px solid\9;border-right:4px solid transparent;border-left:4px solid transparent} .dropdown-toggle:focus{outline:0} .dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;min-width:160px;padding:5px 0;margin:2px 0 0;font-size:14px;text-align:left;list-style:none;background-color:#fff;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175)} .dropdown-menu-right,.dropdown-menu.pull-right{right:0;left:auto} .dropdown-header,.dropdown-menu>li>a{display:block;padding:3px 20px;line-height:1.42857143;white-space:nowrap} .btn-group>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle,.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0} .btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child,.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0} .btn-group-vertical>.btn:not(:first-child):not(:last-child),.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn,.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0} .dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5} .dropdown-menu>li>a{clear:both;font-weight:400;color:#333} .dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{color:#262626;text-decoration:none;background-color:#f5f5f5} .dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{color:#fff;text-decoration:none;background-color:#337ab7;outline:0} .dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{color:#777} .dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{text-decoration:none;cursor:not-allowed;background-color:transparent;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)} .open>.dropdown-menu{display:block} .open>a{outline:0} .dropdown-menu-left{right:auto;left:0} .dropdown-header{font-size:12px;color:#777} .dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990} .nav-justified>.dropdown .dropdown-menu,.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto} .pull-right>.dropdown-menu{right:0;left:auto} .dropup .caret,.navbar-fixed-bottom .dropdown .caret{content:"";border-top:0;border-bottom:4px dashed;border-bottom:4px solid\9} .dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:2px} @media (min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto} .navbar-right .dropdown-menu-left{right:auto;left:0} } .btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle} .btn-group-vertical>.btn,.btn-group>.btn{position:relative;float:left} .btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:2} .btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px} .btn-toolbar{margin-left:-5px} .btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px} .btn .caret,.btn-group>.btn:first-child{margin-left:0} .btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0} .btn-group>.btn+.dropdown-toggle{padding-right:8px;padding-left:8px} .btn-group>.btn-lg+.dropdown-toggle{padding-right:12px;padding-left:12px} .btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)} .btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none} .btn-lg .caret{border-width:5px 5px 0} .dropup .btn-lg .caret{border-width:0 5px 5px} .btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%} .btn-group-vertical>.btn-group>.btn{float:none} .btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0} .btn-group-vertical>.btn:first-child:not(:last-child){border-radius:4px 4px 0 0} .btn-group-vertical>.btn:last-child:not(:first-child){border-radius:0 0 4px 4px} .btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0} .btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0} .btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-top-right-radius:0} .btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate} .btn-group-justified>.btn,.btn-group-justified>.btn-group{display:table-cell;float:none;width:1%} .btn-group-justified>.btn-group .btn{width:100%} .btn-group-justified>.btn-group .dropdown-menu{left:auto} [data-toggle=buttons]>.btn input[type=checkbox],[data-toggle=buttons]>.btn input[type=radio],[data-toggle=buttons]>.btn-group>.btn input[type=checkbox],[data-toggle=buttons]>.btn-group>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none} .input-group{position:relative;display:table;border-collapse:separate} .input-group[class*=col-]{float:none;padding-right:0;padding-left:0} .input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0} .input-group .form-control:focus{z-index:3} .input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px} select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px} select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn,textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn{height:auto} .input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px} select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px} select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn,textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn{height:auto} .input-group .form-control,.input-group-addon,.input-group-btn{display:table-cell} .nav>li,.nav>li>a{display:block;position:relative} .input-group .form-control:not(:first-child):not(:last-child),.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child){border-radius:0} .input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle} .input-group-addon{padding:6px 12px;font-size:14px;font-weight:400;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px} .input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px} .input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px} .input-group-addon input[type=checkbox],.input-group-addon input[type=radio]{margin-top:0} .input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn-group:not(:last-child)>.btn,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0} .input-group-addon:first-child{border-right:0} .input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:first-child>.btn-group:not(:first-child)>.btn,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle{border-top-left-radius:0;border-bottom-left-radius:0} .input-group-addon:last-child{border-left:0} .input-group-btn{position:relative;font-size:0;white-space:nowrap} .input-group-btn>.btn{position:relative} .input-group-btn>.btn+.btn{margin-left:-1px} .input-group-btn>.btn:active,.input-group-btn>.btn:focus,.input-group-btn>.btn:hover{z-index:2} .input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px} .input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{z-index:2;margin-left:-1px} .nav{padding-left:0;margin-bottom:0;list-style:none} .nav>li>a{padding:10px 15px} .nav>li>a:focus,.nav>li>a:hover{text-decoration:none;background-color:#eee} .nav>li.disabled>a{color:#777} .nav>li.disabled>a:focus,.nav>li.disabled>a:hover{color:#777;text-decoration:none;cursor:not-allowed;background-color:transparent} .nav .open>a,.nav .open>a:focus,.nav .open>a:hover{background-color:#eee;border-color:#337ab7} .nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5} .nav>li>a>img{max-width:none} .nav-tabs{border-bottom:1px solid #ddd} .nav-tabs>li{float:left;margin-bottom:-1px} .nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0} .nav-tabs>li>a:hover{border-color:#eee #eee #ddd} .nav-tabs>li.active>a,.nav-tabs>li.active>a:focus,.nav-tabs>li.active>a:hover{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent} .nav-tabs.nav-justified{width:100%;border-bottom:0} .nav-tabs.nav-justified>li{float:none} .nav-tabs.nav-justified>li>a{margin-bottom:5px;text-align:center;margin-right:0;border-radius:4px} .nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border:1px solid #ddd} @media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%} .nav-tabs.nav-justified>li>a{margin-bottom:0;border-bottom:1px solid #ddd;border-radius:4px 4px 0 0} .nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border-bottom-color:#fff} } .nav-pills>li{float:left} .nav-justified>li,.nav-stacked>li{float:none} .nav-pills>li>a{border-radius:4px} .nav-pills>li+li{margin-left:2px} .nav-pills>li.active>a,.nav-pills>li.active>a:focus,.nav-pills>li.active>a:hover{color:#fff;background-color:#337ab7} .nav-stacked>li+li{margin-top:2px;margin-left:0} .nav-justified{width:100%} .nav-justified>li>a{margin-bottom:5px;text-align:center} .nav-tabs-justified{border-bottom:0} .nav-tabs-justified>li>a{margin-right:0;border-radius:4px} .nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border:1px solid #ddd} @media (min-width:768px){.nav-justified>li{display:table-cell;width:1%} .nav-justified>li>a{margin-bottom:0} .nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0} .nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border-bottom-color:#fff} } .tab-content>.tab-pane{display:none} .tab-content>.active{display:block} .nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0} .navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent} .navbar-collapse{padding-right:15px;padding-left:15px;overflow-x:visible;-webkit-overflow-scrolling:touch;border-top:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1)} .navbar-collapse.in{overflow-y:auto} @media (min-width:768px){.navbar{border-radius:4px} .navbar-header{float:left} .navbar-collapse{width:auto;border-top:0;-webkit-box-shadow:none;box-shadow:none} .navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important} .navbar-collapse.in{overflow-y:visible} .navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse{padding-right:0;padding-left:0} } .embed-responsive,.modal,.modal-open,.progress{overflow:hidden} @media (max-device-width:480px) and (orientation:landscape){.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:200px} } .container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:-15px;margin-left:-15px} .navbar-static-top{z-index:1000;border-width:0 0 1px} .navbar-fixed-bottom,.navbar-fixed-top{position:fixed;right:0;left:0;z-index:1030} .navbar-fixed-top{top:0;border-width:0 0 1px} .navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0} .navbar-brand{float:left;height:50px;padding:15px;font-size:18px;line-height:20px} .navbar-brand:focus,.navbar-brand:hover{text-decoration:none} .navbar-brand>img{display:block} @media (min-width:768px){.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:0;margin-left:0} .navbar-fixed-bottom,.navbar-fixed-top,.navbar-static-top{border-radius:0} .navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px} } .navbar-toggle{position:relative;float:right;padding:9px 10px;margin-top:8px;margin-right:15px;margin-bottom:8px;background-color:transparent;border:1px solid transparent;border-radius:4px} .navbar-toggle:focus{outline:0} .navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px} .navbar-toggle .icon-bar+.icon-bar{margin-top:4px} .navbar-nav{margin:7.5px -15px} .navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px} @media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;-webkit-box-shadow:none;box-shadow:none} .navbar-nav .open .dropdown-menu .dropdown-header,.navbar-nav .open .dropdown-menu>li>a{padding:5px 15px 5px 25px} .navbar-nav .open .dropdown-menu>li>a{line-height:20px} .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-nav .open .dropdown-menu>li>a:hover{background-image:none} } .progress-bar-striped,.progress-striped .progress-bar,.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)} @media (min-width:768px){.navbar-toggle{display:none} .navbar-nav{float:left;margin:0} .navbar-nav>li{float:left} .navbar-nav>li>a{padding-top:15px;padding-bottom:15px} } .navbar-form{padding:10px 15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);margin:8px -15px} @media (min-width:768px){.navbar-form .form-control-static,.navbar-form .form-group{display:inline-block} .navbar-form .control-label,.navbar-form .form-group{margin-bottom:0;vertical-align:middle} .navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle} .navbar-form .input-group{display:inline-table;vertical-align:middle} .navbar-form .input-group .form-control,.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn{width:auto} .navbar-form .input-group>.form-control{width:100%} .navbar-form .checkbox,.navbar-form .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle} .navbar-form .checkbox label,.navbar-form .radio label{padding-left:0} .navbar-form .checkbox input[type=checkbox],.navbar-form .radio input[type=radio]{position:relative;margin-left:0} .navbar-form .has-feedback .form-control-feedback{top:0} .navbar-form{width:auto;padding-top:0;padding-bottom:0;margin-right:0;margin-left:0;border:0;-webkit-box-shadow:none;box-shadow:none} } .breadcrumb>li,.pagination{display:inline-block} .btn .badge,.btn .label{top:-1px;position:relative} @media (max-width:767px){.navbar-form .form-group{margin-bottom:5px} .navbar-form .form-group:last-child{margin-bottom:0} } .navbar-nav>li>.dropdown-menu{margin-top:0;border-top-left-radius:0;border-top-right-radius:0} .navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{margin-bottom:0;border-radius:4px 4px 0 0} .navbar-btn{margin-top:8px;margin-bottom:8px} .navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px} .navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px} .navbar-text{margin-top:15px;margin-bottom:15px} @media (min-width:768px){.navbar-text{float:left;margin-right:15px;margin-left:15px} .navbar-left{float:left!important} .navbar-right{float:right!important;margin-right:-15px} .navbar-right~.navbar-right{margin-right:0} } .navbar-default{background-color:#f8f8f8;border-color:#e7e7e7} .navbar-default .navbar-brand{color:#777} .navbar-default .navbar-brand:focus,.navbar-default .navbar-brand:hover{color:#5e5e5e;background-color:transparent} .navbar-default .navbar-nav>li>a,.navbar-default .navbar-text{color:#777} .navbar-default .navbar-nav>li>a:focus,.navbar-default .navbar-nav>li>a:hover{color:#333;background-color:transparent} .navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:focus,.navbar-default .navbar-nav>.active>a:hover{color:#555;background-color:#e7e7e7} .navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:focus,.navbar-default .navbar-nav>.disabled>a:hover{color:#ccc;background-color:transparent} .navbar-default .navbar-toggle{border-color:#ddd} .navbar-default .navbar-toggle:focus,.navbar-default .navbar-toggle:hover{background-color:#ddd} .navbar-default .navbar-toggle .icon-bar{background-color:#888} .navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7} .navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:focus,.navbar-default .navbar-nav>.open>a:hover{color:#555;background-color:#e7e7e7} @media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777} .navbar-default .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover{color:#333;background-color:transparent} .navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover{color:#555;background-color:#e7e7e7} .navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#ccc;background-color:transparent} } .navbar-default .navbar-link{color:#777} .navbar-default .navbar-link:hover{color:#333} .navbar-default .btn-link{color:#777} .navbar-default .btn-link:focus,.navbar-default .btn-link:hover{color:#333} .navbar-default .btn-link[disabled]:focus,.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:focus,fieldset[disabled] .navbar-default .btn-link:hover{color:#ccc} .navbar-inverse{background-color:#222;border-color:#080808} .navbar-inverse .navbar-brand{color:#9d9d9d} .navbar-inverse .navbar-brand:focus,.navbar-inverse .navbar-brand:hover{color:#fff;background-color:transparent} .navbar-inverse .navbar-nav>li>a,.navbar-inverse .navbar-text{color:#9d9d9d} .navbar-inverse .navbar-nav>li>a:focus,.navbar-inverse .navbar-nav>li>a:hover{color:#fff;background-color:transparent} .navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:focus,.navbar-inverse .navbar-nav>.active>a:hover{color:#fff;background-color:#080808} .navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:focus,.navbar-inverse .navbar-nav>.disabled>a:hover{color:#444;background-color:transparent} .navbar-inverse .navbar-toggle{border-color:#333} .navbar-inverse .navbar-toggle:focus,.navbar-inverse .navbar-toggle:hover{background-color:#333} .navbar-inverse .navbar-toggle .icon-bar{background-color:#fff} .navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010} .navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:focus,.navbar-inverse .navbar-nav>.open>a:hover{color:#fff;background-color:#080808} @media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808} .navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808} .navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#9d9d9d} .navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover{color:#fff;background-color:transparent} .navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-color:#080808} .navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#444;background-color:transparent} } .navbar-inverse .navbar-link{color:#9d9d9d} .navbar-inverse .navbar-link:hover{color:#fff} .navbar-inverse .btn-link{color:#9d9d9d} .navbar-inverse .btn-link:focus,.navbar-inverse .btn-link:hover{color:#fff} .navbar-inverse .btn-link[disabled]:focus,.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:focus,fieldset[disabled] .navbar-inverse .btn-link:hover{color:#444} .breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px} .breadcrumb>li+li:before{padding:0 5px;color:#ccc;content:"/\00a0"} .breadcrumb>.active{color:#777} .pagination{padding-left:0;margin:20px 0;border-radius:4px} .pager li,.pagination>li{display:inline} .pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;margin-left:-1px;line-height:1.42857143;color:#337ab7;text-decoration:none;background-color:#fff;border:1px solid #ddd} .pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-top-left-radius:4px;border-bottom-left-radius:4px} .pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:4px;border-bottom-right-radius:4px} .pagination>li>a:focus,.pagination>li>a:hover,.pagination>li>span:focus,.pagination>li>span:hover{z-index:2;color:#23527c;background-color:#eee;border-color:#ddd} .pagination>.active>a,.pagination>.active>a:focus,.pagination>.active>a:hover,.pagination>.active>span,.pagination>.active>span:focus,.pagination>.active>span:hover{z-index:3;color:#fff;cursor:default;background-color:#337ab7;border-color:#337ab7} .pagination>.disabled>a,.pagination>.disabled>a:focus,.pagination>.disabled>a:hover,.pagination>.disabled>span,.pagination>.disabled>span:focus,.pagination>.disabled>span:hover{color:#777;cursor:not-allowed;background-color:#fff;border-color:#ddd} .pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px;line-height:1.3333333} .pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-top-left-radius:6px;border-bottom-left-radius:6px} .pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:6px;border-bottom-right-radius:6px} .pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px;line-height:1.5} .badge,.label{font-weight:700;line-height:1;white-space:nowrap;text-align:center} .pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-top-left-radius:3px;border-bottom-left-radius:3px} .pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:3px;border-bottom-right-radius:3px} .pager{padding-left:0;margin:20px 0;text-align:center;list-style:none} .pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px} .pager li>a:focus,.pager li>a:hover{text-decoration:none;background-color:#eee} .pager .next>a,.pager .next>span{float:right} .pager .previous>a,.pager .previous>span{float:left} .pager .disabled>a,.pager .disabled>a:focus,.pager .disabled>a:hover,.pager .disabled>span{color:#777;cursor:not-allowed;background-color:#fff} a.badge:focus,a.badge:hover,a.label:focus,a.label:hover{color:#fff;cursor:pointer;text-decoration:none} .label{display:inline;padding:.2em .6em .3em;font-size:75%;color:#fff;border-radius:.25em} .label:empty{display:none} .label-default{background-color:#777} .label-default[href]:focus,.label-default[href]:hover{background-color:#5e5e5e} .label-primary{background-color:#337ab7} .label-primary[href]:focus,.label-primary[href]:hover{background-color:#286090} .label-success{background-color:#5cb85c} .label-success[href]:focus,.label-success[href]:hover{background-color:#449d44} .label-info{background-color:#5bc0de} .label-info[href]:focus,.label-info[href]:hover{background-color:#31b0d5} .label-warning{background-color:#f0ad4e} .label-warning[href]:focus,.label-warning[href]:hover{background-color:#ec971f} .label-danger{background-color:#d9534f} .label-danger[href]:focus,.label-danger[href]:hover{background-color:#c9302c} .badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;color:#fff;vertical-align:middle;background-color:#777;border-radius:10px} .badge:empty{display:none} .media-object,.thumbnail{display:block} .btn-group-xs>.btn .badge,.btn-xs .badge{top:0;padding:1px 5px} .list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#337ab7;background-color:#fff} .jumbotron,.jumbotron .h1,.jumbotron h1{color:inherit} .list-group-item>.badge{float:right} .list-group-item>.badge+.badge{margin-right:5px} .nav-pills>li>a>.badge{margin-left:3px} .jumbotron{padding-top:30px;padding-bottom:30px;margin-bottom:30px;background-color:#eee} .jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200} .alert,.thumbnail{margin-bottom:20px} .alert .alert-link,.close{font-weight:700} .jumbotron>hr{border-top-color:#d5d5d5} .container .jumbotron,.container-fluid .jumbotron{padding-right:15px;padding-left:15px;border-radius:6px} .jumbotron .container{max-width:100%} @media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px} .container .jumbotron,.container-fluid .jumbotron{padding-right:60px;padding-left:60px} .jumbotron .h1,.jumbotron h1{font-size:63px} } .thumbnail{padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:border .2s ease-in-out;-o-transition:border .2s ease-in-out;transition:border .2s ease-in-out} .thumbnail a>img,.thumbnail>img{margin-right:auto;margin-left:auto} a.thumbnail.active,a.thumbnail:focus,a.thumbnail:hover{border-color:#337ab7} .thumbnail .caption{padding:9px;color:#333} .alert{padding:15px;border:1px solid transparent;border-radius:4px} .alert h4{margin-top:0;color:inherit} .alert>p,.alert>ul{margin-bottom:0} .alert>p+p{margin-top:5px} .alert-dismissable,.alert-dismissible{padding-right:35px} .alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit} .modal,.modal-backdrop{top:0;right:0;bottom:0;left:0} .alert-success{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6} .alert-success hr{border-top-color:#c9e2b3} .alert-success .alert-link{color:#2b542c} .alert-info{color:#31708f;background-color:#d9edf7;border-color:#bce8f1} .alert-info hr{border-top-color:#a6e1ec} .alert-info .alert-link{color:#245269} .alert-warning{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc} .alert-warning hr{border-top-color:#f7e1b5} .alert-warning .alert-link{color:#66512c} .alert-danger{color:#a94442;background-color:#f2dede;border-color:#ebccd1} .alert-danger hr{border-top-color:#e4b9c0} .alert-danger .alert-link{color:#843534} @-webkit-keyframes progress-bar-stripes{from{background-position:40px 0} to{background-position:0 0} } @-o-keyframes progress-bar-stripes{from{background-position:40px 0} to{background-position:0 0} } @keyframes progress-bar-stripes{from{background-position:40px 0} to{background-position:0 0} } .progress{height:20px;margin-bottom:20px;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)} .progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#337ab7;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease} .progress-bar-striped,.progress-striped .progress-bar{background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;background-size:40px 40px} .progress-bar.active,.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite} .progress-bar-success{background-color:#5cb85c} .progress-striped .progress-bar-success{background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)} .progress-striped .progress-bar-info,.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)} .progress-bar-info{background-color:#5bc0de} .progress-striped .progress-bar-info{background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)} .progress-bar-warning{background-color:#f0ad4e} .progress-striped .progress-bar-warning{background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)} .progress-bar-danger{background-color:#d9534f} .progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)} .media{margin-top:15px} .media:first-child{margin-top:0} .media,.media-body{overflow:hidden;zoom:1} .media-body{width:10000px} .media-object.img-thumbnail{max-width:none} .media-right,.media>.pull-right{padding-left:10px} .media-left,.media>.pull-left{padding-right:10px} .media-body,.media-left,.media-right{display:table-cell;vertical-align:top} .media-middle{vertical-align:middle} .media-bottom{vertical-align:bottom} .media-heading{margin-top:0;margin-bottom:5px} .media-list{padding-left:0;list-style:none} .list-group{padding-left:0;margin-bottom:20px} .list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd} .list-group-item:first-child{border-top-left-radius:4px;border-top-right-radius:4px} .list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px} a.list-group-item,button.list-group-item{color:#555} a.list-group-item .list-group-item-heading,button.list-group-item .list-group-item-heading{color:#333} a.list-group-item:focus,a.list-group-item:hover,button.list-group-item:focus,button.list-group-item:hover{color:#555;text-decoration:none;background-color:#f5f5f5} button.list-group-item{width:100%;text-align:left} .list-group-item.disabled,.list-group-item.disabled:focus,.list-group-item.disabled:hover{color:#777;cursor:not-allowed;background-color:#eee} .list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading{color:inherit} .list-group-item.disabled .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text{color:#777} .list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{z-index:2;color:#fff;background-color:#337ab7;border-color:#337ab7} .list-group-item.active .list-group-item-heading,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:hover .list-group-item-heading>small{color:inherit} .list-group-item.active .list-group-item-text,.list-group-item.active:focus .list-group-item-text,.list-group-item.active:hover .list-group-item-text{color:#c7ddef} .list-group-item-success{color:#3c763d;background-color:#dff0d8} a.list-group-item-success,button.list-group-item-success{color:#3c763d} a.list-group-item-success .list-group-item-heading,button.list-group-item-success .list-group-item-heading{color:inherit} a.list-group-item-success:focus,a.list-group-item-success:hover,button.list-group-item-success:focus,button.list-group-item-success:hover{color:#3c763d;background-color:#d0e9c6} a.list-group-item-success.active,a.list-group-item-success.active:focus,a.list-group-item-success.active:hover,button.list-group-item-success.active,button.list-group-item-success.active:focus,button.list-group-item-success.active:hover{color:#fff;background-color:#3c763d;border-color:#3c763d} .list-group-item-info{color:#31708f;background-color:#d9edf7} a.list-group-item-info,button.list-group-item-info{color:#31708f} a.list-group-item-info .list-group-item-heading,button.list-group-item-info .list-group-item-heading{color:inherit} a.list-group-item-info:focus,a.list-group-item-info:hover,button.list-group-item-info:focus,button.list-group-item-info:hover{color:#31708f;background-color:#c4e3f3} a.list-group-item-info.active,a.list-group-item-info.active:focus,a.list-group-item-info.active:hover,button.list-group-item-info.active,button.list-group-item-info.active:focus,button.list-group-item-info.active:hover{color:#fff;background-color:#31708f;border-color:#31708f} .list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3} a.list-group-item-warning,button.list-group-item-warning{color:#8a6d3b} a.list-group-item-warning .list-group-item-heading,button.list-group-item-warning .list-group-item-heading{color:inherit} a.list-group-item-warning:focus,a.list-group-item-warning:hover,button.list-group-item-warning:focus,button.list-group-item-warning:hover{color:#8a6d3b;background-color:#faf2cc} a.list-group-item-warning.active,a.list-group-item-warning.active:focus,a.list-group-item-warning.active:hover,button.list-group-item-warning.active,button.list-group-item-warning.active:focus,button.list-group-item-warning.active:hover{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b} .list-group-item-danger{color:#a94442;background-color:#f2dede} a.list-group-item-danger,button.list-group-item-danger{color:#a94442} a.list-group-item-danger .list-group-item-heading,button.list-group-item-danger .list-group-item-heading{color:inherit} a.list-group-item-danger:focus,a.list-group-item-danger:hover,button.list-group-item-danger:focus,button.list-group-item-danger:hover{color:#a94442;background-color:#ebcccc} a.list-group-item-danger.active,a.list-group-item-danger.active:focus,a.list-group-item-danger.active:hover,button.list-group-item-danger.active,button.list-group-item-danger.active:focus,button.list-group-item-danger.active:hover{color:#fff;background-color:#a94442;border-color:#a94442} .panel-heading>.dropdown .dropdown-toggle,.panel-title,.panel-title>.small,.panel-title>.small>a,.panel-title>a,.panel-title>small,.panel-title>small>a{color:inherit} .list-group-item-heading{margin-top:0;margin-bottom:5px} .list-group-item-text{margin-bottom:0;line-height:1.3} .panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05);box-shadow:0 1px 1px rgba(0,0,0,.05)} .panel-title,.panel>.list-group,.panel>.panel-collapse>.list-group,.panel>.panel-collapse>.table,.panel>.table,.panel>.table-responsive>.table{margin-bottom:0} .panel-body{padding:15px} .panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-left-radius:3px;border-top-right-radius:3px} .panel-title{margin-top:0;font-size:16px} .panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px} .panel>.list-group .list-group-item,.panel>.panel-collapse>.list-group .list-group-item{border-width:1px 0;border-radius:0} .panel-group .panel-heading,.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th{border-bottom:0} .panel>.list-group:first-child .list-group-item:first-child,.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-left-radius:3px;border-top-right-radius:3px} .panel>.list-group:last-child .list-group-item:last-child,.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px} .panel>.panel-heading+.panel-collapse>.list-group .list-group-item:first-child{border-top-left-radius:0;border-top-right-radius:0} .list-group+.panel-footer,.panel-heading+.list-group .list-group-item:first-child{border-top-width:0} .panel>.panel-collapse>.table caption,.panel>.table caption,.panel>.table-responsive>.table caption{padding-right:15px;padding-left:15px} .panel>.table-responsive:first-child>.table:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,.panel>.table:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child,.panel>.table:first-child>thead:first-child>tr:first-child{border-top-left-radius:3px;border-top-right-radius:3px} .panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child{border-top-left-radius:3px} .panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child{border-top-right-radius:3px} .panel>.table-responsive:last-child>.table:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child,.panel>.table:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px} .panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px} .panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px} .panel>.panel-body+.table,.panel>.panel-body+.table-responsive,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:1px solid #ddd} .panel>.table>tbody:first-child>tr:first-child td,.panel>.table>tbody:first-child>tr:first-child th{border-top:0} .panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0} .panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0} .panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0} .panel>.table-responsive{margin-bottom:0;border:0} .panel-group{margin-bottom:20px} .panel-group .panel{margin-bottom:0;border-radius:4px} .panel-group .panel+.panel{margin-top:5px} .panel-group .panel-heading+.panel-collapse>.list-group,.panel-group .panel-heading+.panel-collapse>.panel-body{border-top:1px solid #ddd} .panel-group .panel-footer{border-top:0} .panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd} .panel-default{border-color:#ddd} .panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd} .panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ddd} .panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333} .panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ddd} .panel-primary{border-color:#337ab7} .panel-primary>.panel-heading{color:#fff;background-color:#337ab7;border-color:#337ab7} .panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#337ab7} .panel-primary>.panel-heading .badge{color:#337ab7;background-color:#fff} .panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#337ab7} .panel-success{border-color:#d6e9c6} .panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6} .panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d6e9c6} .panel-success>.panel-heading .badge{color:#dff0d8;background-color:#3c763d} .panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d6e9c6} .panel-info{border-color:#bce8f1} .panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1} .panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#bce8f1} .panel-info>.panel-heading .badge{color:#d9edf7;background-color:#31708f} .panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#bce8f1} .panel-warning{border-color:#faebcc} .panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc} .panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#faebcc} .panel-warning>.panel-heading .badge{color:#fcf8e3;background-color:#8a6d3b} .panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#faebcc} .panel-danger{border-color:#ebccd1} .panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1} .panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ebccd1} .panel-danger>.panel-heading .badge{color:#f2dede;background-color:#a94442} .panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ebccd1} .embed-responsive{position:relative;display:block;height:0;padding:0} .embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0} .embed-responsive-16by9{padding-bottom:56.25%} .embed-responsive-4by3{padding-bottom:75%} .well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05)} .well blockquote{border-color:#ddd;border-color:rgba(0,0,0,.15)} .well-lg{padding:24px;border-radius:6px} .well-sm{padding:9px;border-radius:3px} .close{float:right;font-size:21px;line-height:1;color:#000;text-shadow:0 1px 0 #fff;filter:alpha(opacity=20);opacity:.2} .popover,.tooltip{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-style:normal;font-weight:400;line-height:1.42857143;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;line-break:auto;text-decoration:none} .close:focus,.close:hover{color:#000;text-decoration:none;cursor:pointer;filter:alpha(opacity=50);opacity:.5} button.close{-webkit-appearance:none;padding:0;cursor:pointer;background:0 0;border:0} .modal{position:fixed;z-index:1050;display:none;-webkit-overflow-scrolling:touch;outline:0} .modal.fade .modal-dialog{-webkit-transition:-webkit-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out;-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);-o-transform:translate(0,-25%);transform:translate(0,-25%)} .modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);-o-transform:translate(0,0);transform:translate(0,0)} .modal-open .modal{overflow-x:hidden;overflow-y:auto} .modal-dialog{position:relative;width:auto;margin:10px} .modal-content{position:relative;background-color:#fff;background-clip:padding-box;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;outline:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5)} .modal-backdrop{position:fixed;z-index:1040;background-color:#000} .modal-backdrop.fade{filter:alpha(opacity=0);opacity:0} .modal-backdrop.in{filter:alpha(opacity=50);opacity:.5} .modal-header{padding:15px;border-bottom:1px solid #e5e5e5} .modal-header .close{margin-top:-2px} .modal-title{margin:0;line-height:1.42857143} .modal-body{position:relative;padding:15px} .modal-footer{padding:15px;text-align:right;border-top:1px solid #e5e5e5} .modal-footer .btn+.btn{margin-bottom:0;margin-left:5px} .modal-footer .btn-group .btn+.btn{margin-left:-1px} .modal-footer .btn-block+.btn-block{margin-left:0} .modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll} @media (min-width:768px){.modal-dialog{width:600px;margin:30px auto} .modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,.5);box-shadow:0 5px 15px rgba(0,0,0,.5)} .modal-sm{width:300px} } @media (min-width:992px){.modal-lg{width:900px} } .tooltip{position:absolute;z-index:1070;display:block;font-size:12px;text-align:left;text-align:start;filter:alpha(opacity=0);opacity:0} .tooltip.in{filter:alpha(opacity=90);opacity:.9} .tooltip.top{padding:5px 0;margin-top:-3px} .tooltip.right{padding:0 5px;margin-left:3px} .tooltip.bottom{padding:5px 0;margin-top:3px} .tooltip.left{padding:0 5px;margin-left:-3px} .tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;background-color:#000;border-radius:4px} .tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid} .tooltip.top .tooltip-arrow,.tooltip.top-left .tooltip-arrow,.tooltip.top-right .tooltip-arrow{bottom:0;border-width:5px 5px 0;border-top-color:#000} .tooltip.top .tooltip-arrow{left:50%;margin-left:-5px} .tooltip.top-left .tooltip-arrow{right:5px;margin-bottom:-5px} .tooltip.top-right .tooltip-arrow{left:5px;margin-bottom:-5px} .tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000} .tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000} .tooltip.bottom .tooltip-arrow,.tooltip.bottom-left .tooltip-arrow,.tooltip.bottom-right .tooltip-arrow{border-width:0 5px 5px;border-bottom-color:#000;top:0} .tooltip.bottom .tooltip-arrow{left:50%;margin-left:-5px} .tooltip.bottom-left .tooltip-arrow{right:5px;margin-top:-5px} .tooltip.bottom-right .tooltip-arrow{left:5px;margin-top:-5px} .popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;font-size:14px;text-align:left;text-align:start;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2)} .carousel-caption,.carousel-control{color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)} .popover.top{margin-top:-10px} .popover.right{margin-left:10px} .popover.bottom{margin-top:10px} .popover.left{margin-left:-10px} .popover-title{padding:8px 14px;margin:0;font-size:14px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0} .popover-content{padding:9px 14px} .popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid} .carousel,.carousel-inner{position:relative} .popover>.arrow{border-width:11px} .popover>.arrow:after{content:"";border-width:10px} .popover.top>.arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,.25);border-bottom-width:0} .popover.top>.arrow:after{bottom:1px;margin-left:-10px;content:" ";border-top-color:#fff;border-bottom-width:0} .popover.left>.arrow:after,.popover.right>.arrow:after{bottom:-10px;content:" "} .popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,.25);border-left-width:0} .popover.right>.arrow:after{left:1px;border-right-color:#fff;border-left-width:0} .popover.bottom>.arrow{top:-11px;left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,.25)} .popover.bottom>.arrow:after{top:1px;margin-left:-10px;content:" ";border-top-width:0;border-bottom-color:#fff} .popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,.25)} .popover.left>.arrow:after{right:1px;border-right-width:0;border-left-color:#fff} .carousel-inner{width:100%;overflow:hidden} .carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left} .carousel-inner>.item>a>img,.carousel-inner>.item>img{line-height:1} @media all and (transform-3d),(-webkit-transform-3d){.carousel-inner>.item{-webkit-transition:-webkit-transform .6s ease-in-out;-o-transition:-o-transform .6s ease-in-out;transition:transform .6s ease-in-out;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px} .carousel-inner>.item.active.right,.carousel-inner>.item.next{left:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)} .carousel-inner>.item.active.left,.carousel-inner>.item.prev{left:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)} .carousel-inner>.item.active,.carousel-inner>.item.next.left,.carousel-inner>.item.prev.right{left:0;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)} } .carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block} .carousel-inner>.active{left:0} .carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%} .carousel-inner>.next{left:100%} .carousel-inner>.prev{left:-100%} .carousel-inner>.next.left,.carousel-inner>.prev.right{left:0} .carousel-inner>.active.left{left:-100%} .carousel-inner>.active.right{left:100%} .carousel-control{position:absolute;top:0;bottom:0;left:0;width:15%;font-size:20px;background-color:rgba(0,0,0,0);filter:alpha(opacity=50);opacity:.5} .carousel-control.left{background-image:-webkit-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.5)),to(rgba(0,0,0,.0001)));background-image:linear-gradient(to right,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);background-repeat:repeat-x} .carousel-control.right{right:0;left:auto;background-image:-webkit-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.0001)),to(rgba(0,0,0,.5)));background-image:linear-gradient(to right,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);background-repeat:repeat-x} .carousel-control:focus,.carousel-control:hover{color:#fff;text-decoration:none;filter:alpha(opacity=90);outline:0;opacity:.9} .carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{position:absolute;top:50%;z-index:5;display:inline-block;margin-top:-10px} .carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{left:50%;margin-left:-10px} .carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{right:50%;margin-right:-10px} .carousel-control .icon-next,.carousel-control .icon-prev{width:20px;height:20px;font-family:serif;line-height:1} .carousel-control .icon-prev:before{content:'\2039'} .carousel-control .icon-next:before{content:'\203a'} .carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;padding-left:0;margin-left:-30%;text-align:center;list-style:none} .carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;cursor:pointer;background-color:#000\9;background-color:rgba(0,0,0,0);border:1px solid #fff;border-radius:10px} .carousel-indicators .active{width:12px;height:12px;margin:0;background-color:#fff} .carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px} .carousel-caption .btn,.text-hide{text-shadow:none} @media screen and (min-width:768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{width:30px;height:30px;margin-top:-10px;font-size:30px} .carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-10px} .carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-10px} .carousel-caption{right:20%;left:20%;padding-bottom:30px} .carousel-indicators{bottom:20px} } .btn-group-vertical>.btn-group:after,.btn-group-vertical>.btn-group:before,.btn-toolbar:after,.btn-toolbar:before,.clearfix:after,.clearfix:before,.container-fluid:after,.container-fluid:before,.container:after,.container:before,.dl-horizontal dd:after,.dl-horizontal dd:before,.form-horizontal .form-group:after,.form-horizontal .form-group:before,.modal-footer:after,.modal-footer:before,.modal-header:after,.modal-header:before,.nav:after,.nav:before,.navbar-collapse:after,.navbar-collapse:before,.navbar-header:after,.navbar-header:before,.navbar:after,.navbar:before,.pager:after,.pager:before,.panel-body:after,.panel-body:before,.row:after,.row:before{display:table;content:" "} .btn-group-vertical>.btn-group:after,.btn-toolbar:after,.clearfix:after,.container-fluid:after,.container:after,.dl-horizontal dd:after,.form-horizontal .form-group:after,.modal-footer:after,.modal-header:after,.nav:after,.navbar-collapse:after,.navbar-header:after,.navbar:after,.pager:after,.panel-body:after,.row:after{clear:both} .center-block{display:block;margin-right:auto;margin-left:auto} .pull-right{float:right!important} .pull-left{float:left!important} .hide{display:none!important} .show{display:block!important} .hidden,.visible-lg,.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block,.visible-md,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-sm,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-xs,.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block{display:none!important} .invisible{visibility:hidden} .text-hide{font:0/0 a;color:transparent;background-color:transparent;border:0} .affix{position:fixed} @-ms-viewport{width:device-width} @media (max-width:767px){.visible-xs{display:block!important} table.visible-xs{display:table!important} tr.visible-xs{display:table-row!important} td.visible-xs,th.visible-xs{display:table-cell!important} .visible-xs-block{display:block!important} .visible-xs-inline{display:inline!important} .visible-xs-inline-block{display:inline-block!important} } @media (min-width:768px) and (max-width:991px){.visible-sm{display:block!important} table.visible-sm{display:table!important} tr.visible-sm{display:table-row!important} td.visible-sm,th.visible-sm{display:table-cell!important} .visible-sm-block{display:block!important} .visible-sm-inline{display:inline!important} .visible-sm-inline-block{display:inline-block!important} } @media (min-width:992px) and (max-width:1199px){.visible-md{display:block!important} table.visible-md{display:table!important} tr.visible-md{display:table-row!important} td.visible-md,th.visible-md{display:table-cell!important} .visible-md-block{display:block!important} .visible-md-inline{display:inline!important} .visible-md-inline-block{display:inline-block!important} } @media (min-width:1200px){.visible-lg{display:block!important} table.visible-lg{display:table!important} tr.visible-lg{display:table-row!important} td.visible-lg,th.visible-lg{display:table-cell!important} .visible-lg-block{display:block!important} .visible-lg-inline{display:inline!important} .visible-lg-inline-block{display:inline-block!important} .hidden-lg{display:none!important} } @media (max-width:767px){.hidden-xs{display:none!important} } @media (min-width:768px) and (max-width:991px){.hidden-sm{display:none!important} } @media (min-width:992px) and (max-width:1199px){.hidden-md{display:none!important} } .visible-print{display:none!important} @media print{.visible-print{display:block!important} table.visible-print{display:table!important} tr.visible-print{display:table-row!important} td.visible-print,th.visible-print{display:table-cell!important} } .visible-print-block{display:none!important} @media print{.visible-print-block{display:block!important} } .visible-print-inline{display:none!important} @media print{.visible-print-inline{display:inline!important} } .visible-print-inline-block{display:none!important} @media print{.visible-print-inline-block{display:inline-block!important} .hidden-print{display:none!important} } .hljs{display:block;background:#fff;padding:.5em;color:#333;overflow-x:auto} .hljs-comment,.hljs-meta{color:#969896} .hljs-emphasis,.hljs-quote,.hljs-string,.hljs-strong,.hljs-template-variable,.hljs-variable{color:#df5000} .hljs-keyword,.hljs-selector-tag,.hljs-type{color:#a71d5d} .hljs-attribute,.hljs-bullet,.hljs-literal,.hljs-symbol{color:#0086b3} .hljs-name,.hljs-section{color:#63a35c} .hljs-tag{color:#333} .hljs-attr,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-id,.hljs-selector-pseudo,.hljs-title{color:#795da3} .hljs-addition{color:#55a532;background-color:#eaffea} .hljs-deletion{color:#bd2c00;background-color:#ffecec} .hljs-link{text-decoration:underline} ================================================ FILE: ERC/docs/styles/docfx.vendor.js ================================================ /*! jQuery v2.1.4 | (c) 2005, 2015 jQuery Foundation, Inc. | jquery.org/license */ !function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k={},l=a.document,m="2.1.4",n=function(a,b){return new n.fn.init(a,b)},o=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,p=/^-ms-/,q=/-([\da-z])/gi,r=function(a,b){return b.toUpperCase()};n.fn=n.prototype={jquery:m,constructor:n,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return n.each(this,a,b)},map:function(a){return this.pushStack(n.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},n.extend=n.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||n.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(a=arguments[h]))for(b in a)c=g[b],d=a[b],g!==d&&(j&&d&&(n.isPlainObject(d)||(e=n.isArray(d)))?(e?(e=!1,f=c&&n.isArray(c)?c:[]):f=c&&n.isPlainObject(c)?c:{},g[b]=n.extend(j,f,d)):void 0!==d&&(g[b]=d));return g},n.extend({expando:"jQuery"+(m+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===n.type(a)},isArray:Array.isArray,isWindow:function(a){return null!=a&&a===a.window},isNumeric:function(a){return!n.isArray(a)&&a-parseFloat(a)+1>=0},isPlainObject:function(a){return"object"!==n.type(a)||a.nodeType||n.isWindow(a)?!1:a.constructor&&!j.call(a.constructor.prototype,"isPrototypeOf")?!1:!0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(a){var b,c=eval;a=n.trim(a),a&&(1===a.indexOf("use strict")?(b=l.createElement("script"),b.text=a,l.head.appendChild(b).parentNode.removeChild(b)):c(a))},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=s(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(o,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){return null==b?-1:g.call(b,a,c)},merge:function(a,b){for(var c=+b.length,d=0,e=a.length;c>d;d++)a[e++]=b[d];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=s(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(c=a[b],b=a,a=c),n.isFunction(a)?(e=d.call(arguments,2),f=function(){return a.apply(b||this,e.concat(d.call(arguments)))},f.guid=a.guid=a.guid||n.guid++,f):void 0},now:Date.now,support:k}),n.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function s(a){var b="length"in a&&a.length,c=n.type(a);return"function"===c||n.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ha(),z=ha(),A=ha(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",L="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",N=M.replace("w","w#"),O="\\["+L+"*("+M+")(?:"+L+"*([*^$|!~]?=)"+L+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+N+"))|)"+L+"*\\]",P=":("+M+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+O+")*)|.*)\\)|)",Q=new RegExp(L+"+","g"),R=new RegExp("^"+L+"+|((?:^|[^\\\\])(?:\\\\.)*)"+L+"+$","g"),S=new RegExp("^"+L+"*,"+L+"*"),T=new RegExp("^"+L+"*([>+~]|"+L+")"+L+"*"),U=new RegExp("="+L+"*([^\\]'\"]*?)"+L+"*\\]","g"),V=new RegExp(P),W=new RegExp("^"+N+"$"),X={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),TAG:new RegExp("^("+M.replace("w","w*")+")"),ATTR:new RegExp("^"+O),PSEUDO:new RegExp("^"+P),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+L+"*(even|odd|(([+-]|)(\\d*)n|)"+L+"*(?:([+-]|)"+L+"*(\\d+)|))"+L+"*\\)|)","i"),bool:new RegExp("^(?:"+K+")$","i"),needsContext:new RegExp("^"+L+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+L+"*((?:-\\d)?\\d*)"+L+"*\\)|)(?=[^-]|$)","i")},Y=/^(?:input|select|textarea|button)$/i,Z=/^h\d$/i,$=/^[^{]+\{\s*\[native \w/,_=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,aa=/[+~]/,ba=/'|\\/g,ca=new RegExp("\\\\([\\da-f]{1,6}"+L+"?|("+L+")|.)","ig"),da=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},ea=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(fa){H={apply:E.length?function(a,b){G.apply(a,I.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function ga(a,b,d,e){var f,h,j,k,l,o,r,s,w,x;if((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,d=d||[],k=b.nodeType,"string"!=typeof a||!a||1!==k&&9!==k&&11!==k)return d;if(!e&&p){if(11!==k&&(f=_.exec(a)))if(j=f[1]){if(9===k){if(h=b.getElementById(j),!h||!h.parentNode)return d;if(h.id===j)return d.push(h),d}else if(b.ownerDocument&&(h=b.ownerDocument.getElementById(j))&&t(b,h)&&h.id===j)return d.push(h),d}else{if(f[2])return H.apply(d,b.getElementsByTagName(a)),d;if((j=f[3])&&c.getElementsByClassName)return H.apply(d,b.getElementsByClassName(j)),d}if(c.qsa&&(!q||!q.test(a))){if(s=r=u,w=b,x=1!==k&&a,1===k&&"object"!==b.nodeName.toLowerCase()){o=g(a),(r=b.getAttribute("id"))?s=r.replace(ba,"\\$&"):b.setAttribute("id",s),s="[id='"+s+"'] ",l=o.length;while(l--)o[l]=s+ra(o[l]);w=aa.test(a)&&pa(b.parentNode)||b,x=o.join(",")}if(x)try{return H.apply(d,w.querySelectorAll(x)),d}catch(y){}finally{r||b.removeAttribute("id")}}}return i(a.replace(R,"$1"),b,d,e)}function ha(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ia(a){return a[u]=!0,a}function ja(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ka(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function la(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||C)-(~a.sourceIndex||C);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function na(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function oa(a){return ia(function(b){return b=+b,ia(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function pa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=ga.support={},f=ga.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=ga.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=g.documentElement,e=g.defaultView,e&&e!==e.top&&(e.addEventListener?e.addEventListener("unload",ea,!1):e.attachEvent&&e.attachEvent("onunload",ea)),p=!f(g),c.attributes=ja(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ja(function(a){return a.appendChild(g.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=$.test(g.getElementsByClassName),c.getById=ja(function(a){return o.appendChild(a).id=u,!g.getElementsByName||!g.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(ca,da);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(ca,da);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=$.test(g.querySelectorAll))&&(ja(function(a){o.appendChild(a).innerHTML="",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+L+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+L+"*(?:value|"+K+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ja(function(a){var b=g.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+L+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=$.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ja(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",P)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=$.test(o.compareDocumentPosition),t=b||$.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===g||a.ownerDocument===v&&t(v,a)?-1:b===g||b.ownerDocument===v&&t(v,b)?1:k?J(k,a)-J(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,h=[a],i=[b];if(!e||!f)return a===g?-1:b===g?1:e?-1:f?1:k?J(k,a)-J(k,b):0;if(e===f)return la(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)i.unshift(c);while(h[d]===i[d])d++;return d?la(h[d],i[d]):h[d]===v?-1:i[d]===v?1:0},g):n},ga.matches=function(a,b){return ga(a,null,null,b)},ga.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(U,"='$1']"),!(!c.matchesSelector||!p||r&&r.test(b)||q&&q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return ga(b,n,null,[a]).length>0},ga.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},ga.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&D.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},ga.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},ga.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=ga.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=ga.selectors={cacheLength:50,createPseudo:ia,match:X,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(ca,da),a[3]=(a[3]||a[4]||a[5]||"").replace(ca,da),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||ga.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&ga.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return X.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&V.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(ca,da).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+L+")"+a+"("+L+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=ga.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(Q," ")+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){k=q[u]||(q[u]={}),j=k[a]||[],n=j[0]===w&&j[1],m=j[0]===w&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[w,n,m];break}}else if(s&&(j=(b[u]||(b[u]={}))[a])&&j[0]===w)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(s&&((l[u]||(l[u]={}))[a]=[w,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||ga.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ia(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=J(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ia(function(a){var b=[],c=[],d=h(a.replace(R,"$1"));return d[u]?ia(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ia(function(a){return function(b){return ga(a,b).length>0}}),contains:ia(function(a){return a=a.replace(ca,da),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ia(function(a){return W.test(a||"")||ga.error("unsupported lang: "+a),a=a.replace(ca,da).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Z.test(a.nodeName)},input:function(a){return Y.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:oa(function(){return[0]}),last:oa(function(a,b){return[b-1]}),eq:oa(function(a,b,c){return[0>c?c+b:c]}),even:oa(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:oa(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:oa(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:oa(function(a,b,c){for(var d=0>c?c+b:c;++db;b++)d+=a[b].value;return d}function sa(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[u]||(b[u]={}),(h=i[d])&&h[0]===w&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function ta(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function ua(a,b,c){for(var d=0,e=b.length;e>d;d++)ga(a,b[d],c);return c}function va(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function wa(a,b,c,d,e,f){return d&&!d[u]&&(d=wa(d)),e&&!e[u]&&(e=wa(e,f)),ia(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ua(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:va(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=va(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?J(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=va(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function xa(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=sa(function(a){return a===b},h,!0),l=sa(function(a){return J(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];f>i;i++)if(c=d.relative[a[i].type])m=[sa(ta(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return wa(i>1&&ta(m),i>1&&ra(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(R,"$1"),c,e>i&&xa(a.slice(i,e)),f>e&&xa(a=a.slice(e)),f>e&&ra(a))}m.push(c)}return ta(m)}function ya(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,m,o,p=0,q="0",r=f&&[],s=[],t=j,u=f||e&&d.find.TAG("*",k),v=w+=null==t?1:Math.random()||.1,x=u.length;for(k&&(j=g!==n&&g);q!==x&&null!=(l=u[q]);q++){if(e&&l){m=0;while(o=a[m++])if(o(l,g,h)){i.push(l);break}k&&(w=v)}c&&((l=!o&&l)&&p--,f&&r.push(l))}if(p+=q,c&&q!==p){m=0;while(o=b[m++])o(r,s,g,h);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=F.call(i));s=va(s)}H.apply(i,s),k&&!f&&s.length>0&&p+b.length>1&&ga.uniqueSort(i)}return k&&(w=v,j=t),r};return c?ia(f):f}return h=ga.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=xa(b[c]),f[u]?d.push(f):e.push(f);f=A(a,ya(e,d)),f.selector=a}return f},i=ga.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(ca,da),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=X.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(ca,da),aa.test(j[0].type)&&pa(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&ra(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,aa.test(a)&&pa(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ja(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ja(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||ka("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ja(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ka("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ja(function(a){return null==a.getAttribute("disabled")})||ka(K,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),ga}(a);n.find=t,n.expr=t.selectors,n.expr[":"]=n.expr.pseudos,n.unique=t.uniqueSort,n.text=t.getText,n.isXMLDoc=t.isXML,n.contains=t.contains;var u=n.expr.match.needsContext,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^.[^:#\[\.,]*$/;function x(a,b,c){if(n.isFunction(b))return n.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return n.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(w.test(b))return n.filter(b,a,c);b=n.filter(b,a)}return n.grep(a,function(a){return g.call(b,a)>=0!==c})}n.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?n.find.matchesSelector(d,a)?[d]:[]:n.find.matches(a,n.grep(b,function(a){return 1===a.nodeType}))},n.fn.extend({find:function(a){var b,c=this.length,d=[],e=this;if("string"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;c>b;b++)if(n.contains(e[b],this))return!0}));for(b=0;c>b;b++)n.find(a,e[b],d);return d=this.pushStack(c>1?n.unique(d):d),d.selector=this.selector?this.selector+" "+a:a,d},filter:function(a){return this.pushStack(x(this,a||[],!1))},not:function(a){return this.pushStack(x(this,a||[],!0))},is:function(a){return!!x(this,"string"==typeof a&&u.test(a)?n(a):a||[],!1).length}});var y,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=n.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||y).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof n?b[0]:b,n.merge(this,n.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:l,!0)),v.test(c[1])&&n.isPlainObject(b))for(c in b)n.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}return d=l.getElementById(c[2]),d&&d.parentNode&&(this.length=1,this[0]=d),this.context=l,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?"undefined"!=typeof y.ready?y.ready(a):a(n):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),n.makeArray(a,this))};A.prototype=n.fn,y=n(l);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};n.extend({dir:function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&n(a).is(c))break;d.push(a)}return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),n.fn.extend({has:function(a){var b=n(a,this),c=b.length;return this.filter(function(){for(var a=0;c>a;a++)if(n.contains(this,b[a]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=u.test(a)||"string"!=typeof a?n(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&n.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?n.unique(f):f)},index:function(a){return a?"string"==typeof a?g.call(n(a),this[0]):g.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(n.unique(n.merge(this.get(),n(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){while((a=a[b])&&1!==a.nodeType);return a}n.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return n.dir(a,"parentNode")},parentsUntil:function(a,b,c){return n.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return n.dir(a,"nextSibling")},prevAll:function(a){return n.dir(a,"previousSibling")},nextUntil:function(a,b,c){return n.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return n.dir(a,"previousSibling",c)},siblings:function(a){return n.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return n.sibling(a.firstChild)},contents:function(a){return a.contentDocument||n.merge([],a.childNodes)}},function(a,b){n.fn[a]=function(c,d){var e=n.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=n.filter(d,e)),this.length>1&&(C[a]||n.unique(e),B.test(a)&&e.reverse()),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return n.each(a.match(E)||[],function(a,c){b[c]=!0}),b}n.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):n.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(b=a.memory&&l,c=!0,g=e||0,e=0,f=h.length,d=!0;h&&f>g;g++)if(h[g].apply(l[0],l[1])===!1&&a.stopOnFalse){b=!1;break}d=!1,h&&(i?i.length&&j(i.shift()):b?h=[]:k.disable())},k={add:function(){if(h){var c=h.length;!function g(b){n.each(b,function(b,c){var d=n.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&g(c)})}(arguments),d?f=h.length:b&&(e=c,j(b))}return this},remove:function(){return h&&n.each(arguments,function(a,b){var c;while((c=n.inArray(b,h,c))>-1)h.splice(c,1),d&&(f>=c&&f--,g>=c&&g--)}),this},has:function(a){return a?n.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],f=0,this},disable:function(){return h=i=b=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,b||k.disable(),this},locked:function(){return!i},fireWith:function(a,b){return!h||c&&!i||(b=b||[],b=[a,b.slice?b.slice():b],d?i.push(b):j(b)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!c}};return k},n.extend({Deferred:function(a){var b=[["resolve","done",n.Callbacks("once memory"),"resolved"],["reject","fail",n.Callbacks("once memory"),"rejected"],["notify","progress",n.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return n.Deferred(function(c){n.each(b,function(b,f){var g=n.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&n.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?n.extend(a,d):d}},e={};return d.pipe=d.then,n.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&n.isFunction(a.promise)?e:0,g=1===f?a:n.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&n.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;n.fn.ready=function(a){return n.ready.promise().done(a),this},n.extend({isReady:!1,readyWait:1,holdReady:function(a){a?n.readyWait++:n.ready(!0)},ready:function(a){(a===!0?--n.readyWait:n.isReady)||(n.isReady=!0,a!==!0&&--n.readyWait>0||(H.resolveWith(l,[n]),n.fn.triggerHandler&&(n(l).triggerHandler("ready"),n(l).off("ready"))))}});function I(){l.removeEventListener("DOMContentLoaded",I,!1),a.removeEventListener("load",I,!1),n.ready()}n.ready.promise=function(b){return H||(H=n.Deferred(),"complete"===l.readyState?setTimeout(n.ready):(l.addEventListener("DOMContentLoaded",I,!1),a.addEventListener("load",I,!1))),H.promise(b)},n.ready.promise();var J=n.access=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===n.type(c)){e=!0;for(h in c)n.access(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,n.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(n(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f};n.acceptData=function(a){return 1===a.nodeType||9===a.nodeType||!+a.nodeType};function K(){Object.defineProperty(this.cache={},0,{get:function(){return{}}}),this.expando=n.expando+K.uid++}K.uid=1,K.accepts=n.acceptData,K.prototype={key:function(a){if(!K.accepts(a))return 0;var b={},c=a[this.expando];if(!c){c=K.uid++;try{b[this.expando]={value:c},Object.defineProperties(a,b)}catch(d){b[this.expando]=c,n.extend(a,b)}}return this.cache[c]||(this.cache[c]={}),c},set:function(a,b,c){var d,e=this.key(a),f=this.cache[e];if("string"==typeof b)f[b]=c;else if(n.isEmptyObject(f))n.extend(this.cache[e],b);else for(d in b)f[d]=b[d];return f},get:function(a,b){var c=this.cache[this.key(a)];return void 0===b?c:c[b]},access:function(a,b,c){var d;return void 0===b||b&&"string"==typeof b&&void 0===c?(d=this.get(a,b),void 0!==d?d:this.get(a,n.camelCase(b))):(this.set(a,b,c),void 0!==c?c:b)},remove:function(a,b){var c,d,e,f=this.key(a),g=this.cache[f];if(void 0===b)this.cache[f]={};else{n.isArray(b)?d=b.concat(b.map(n.camelCase)):(e=n.camelCase(b),b in g?d=[b,e]:(d=e,d=d in g?[d]:d.match(E)||[])),c=d.length;while(c--)delete g[d[c]]}},hasData:function(a){return!n.isEmptyObject(this.cache[a[this.expando]]||{})},discard:function(a){a[this.expando]&&delete this.cache[a[this.expando]]}};var L=new K,M=new K,N=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,O=/([A-Z])/g;function P(a,b,c){var d;if(void 0===c&&1===a.nodeType)if(d="data-"+b.replace(O,"-$1").toLowerCase(),c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:N.test(c)?n.parseJSON(c):c}catch(e){}M.set(a,b,c)}else c=void 0;return c}n.extend({hasData:function(a){return M.hasData(a)||L.hasData(a)},data:function(a,b,c){ return M.access(a,b,c)},removeData:function(a,b){M.remove(a,b)},_data:function(a,b,c){return L.access(a,b,c)},_removeData:function(a,b){L.remove(a,b)}}),n.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=M.get(f),1===f.nodeType&&!L.get(f,"hasDataAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=n.camelCase(d.slice(5)),P(f,d,e[d])));L.set(f,"hasDataAttrs",!0)}return e}return"object"==typeof a?this.each(function(){M.set(this,a)}):J(this,function(b){var c,d=n.camelCase(a);if(f&&void 0===b){if(c=M.get(f,a),void 0!==c)return c;if(c=M.get(f,d),void 0!==c)return c;if(c=P(f,d,void 0),void 0!==c)return c}else this.each(function(){var c=M.get(this,d);M.set(this,d,b),-1!==a.indexOf("-")&&void 0!==c&&M.set(this,a,b)})},null,b,arguments.length>1,null,!0)},removeData:function(a){return this.each(function(){M.remove(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=L.get(a,b),c&&(!d||n.isArray(c)?d=L.access(a,b,n.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=n.queue(a,b),d=c.length,e=c.shift(),f=n._queueHooks(a,b),g=function(){n.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return L.get(a,c)||L.access(a,c,{empty:n.Callbacks("once memory").add(function(){L.remove(a,[b+"queue",c])})})}}),n.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.lengthx",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var U="undefined";k.focusinBubbles="onfocusin"in a;var V=/^key/,W=/^(?:mouse|pointer|contextmenu)|click/,X=/^(?:focusinfocus|focusoutblur)$/,Y=/^([^.]*)(?:\.(.+)|)$/;function Z(){return!0}function $(){return!1}function _(){try{return l.activeElement}catch(a){}}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=L.get(a);if(r){c.handler&&(f=c,c=f.handler,e=f.selector),c.guid||(c.guid=n.guid++),(i=r.events)||(i=r.events={}),(g=r.handle)||(g=r.handle=function(b){return typeof n!==U&&n.event.triggered!==b.type?n.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(E)||[""],j=b.length;while(j--)h=Y.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o&&(l=n.event.special[o]||{},o=(e?l.delegateType:l.bindType)||o,l=n.event.special[o]||{},k=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},f),(m=i[o])||(m=i[o]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,p,g)!==!1||a.addEventListener&&a.addEventListener(o,g,!1)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),n.event.global[o]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=L.hasData(a)&&L.get(a);if(r&&(i=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=Y.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=i[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&q!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete i[o])}else for(o in i)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(i)&&(delete r.handle,L.remove(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,m,o,p=[d||l],q=j.call(b,"type")?b.type:b,r=j.call(b,"namespace")?b.namespace.split("."):[];if(g=h=d=d||l,3!==d.nodeType&&8!==d.nodeType&&!X.test(q+n.event.triggered)&&(q.indexOf(".")>=0&&(r=q.split("."),q=r.shift(),r.sort()),k=q.indexOf(":")<0&&"on"+q,b=b[n.expando]?b:new n.Event(q,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=r.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+r.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:n.makeArray(c,[b]),o=n.event.special[q]||{},e||!o.trigger||o.trigger.apply(d,c)!==!1)){if(!e&&!o.noBubble&&!n.isWindow(d)){for(i=o.delegateType||q,X.test(i+q)||(g=g.parentNode);g;g=g.parentNode)p.push(g),h=g;h===(d.ownerDocument||l)&&p.push(h.defaultView||h.parentWindow||a)}f=0;while((g=p[f++])&&!b.isPropagationStopped())b.type=f>1?i:o.bindType||q,m=(L.get(g,"events")||{})[b.type]&&L.get(g,"handle"),m&&m.apply(g,c),m=k&&g[k],m&&m.apply&&n.acceptData(g)&&(b.result=m.apply(g,c),b.result===!1&&b.preventDefault());return b.type=q,e||b.isDefaultPrevented()||o._default&&o._default.apply(p.pop(),c)!==!1||!n.acceptData(d)||k&&n.isFunction(d[q])&&!n.isWindow(d)&&(h=d[k],h&&(d[k]=null),n.event.triggered=q,d[q](),n.event.triggered=void 0,h&&(d[k]=h)),b.result}},dispatch:function(a){a=n.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(L.get(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(g.namespace))&&(a.handleObj=g,a.data=g.data,e=((n.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==e&&(a.result=e)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!==this;i=i.parentNode||this)if(i.disabled!==!0||"click"!==a.type){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?n(e,this).index(i)>=0:n.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h]*)\/>/gi,ba=/<([\w:]+)/,ca=/<|&#?\w+;/,da=/<(?:script|style|link)/i,ea=/checked\s*(?:[^=]|=\s*.checked.)/i,fa=/^$|\/(?:java|ecma)script/i,ga=/^true\/(.*)/,ha=/^\s*\s*$/g,ia={option:[1,""],thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};ia.optgroup=ia.option,ia.tbody=ia.tfoot=ia.colgroup=ia.caption=ia.thead,ia.th=ia.td;function ja(a,b){return n.nodeName(a,"table")&&n.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function ka(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function la(a){var b=ga.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function ma(a,b){for(var c=0,d=a.length;d>c;c++)L.set(a[c],"globalEval",!b||L.get(b[c],"globalEval"))}function na(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(L.hasData(a)&&(f=L.access(a),g=L.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;d>c;c++)n.event.add(b,e,j[e][c])}M.hasData(a)&&(h=M.access(a),i=n.extend({},h),M.set(b,i))}}function oa(a,b){var c=a.getElementsByTagName?a.getElementsByTagName(b||"*"):a.querySelectorAll?a.querySelectorAll(b||"*"):[];return void 0===b||b&&n.nodeName(a,b)?n.merge([a],c):c}function pa(a,b){var c=b.nodeName.toLowerCase();"input"===c&&T.test(a.type)?b.checked=a.checked:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}n.extend({clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=n.contains(a.ownerDocument,a);if(!(k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(g=oa(h),f=oa(a),d=0,e=f.length;e>d;d++)pa(f[d],g[d]);if(b)if(c)for(f=f||oa(a),g=g||oa(h),d=0,e=f.length;e>d;d++)na(f[d],g[d]);else na(a,h);return g=oa(h,"script"),g.length>0&&ma(g,!i&&oa(a,"script")),h},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,k=b.createDocumentFragment(),l=[],m=0,o=a.length;o>m;m++)if(e=a[m],e||0===e)if("object"===n.type(e))n.merge(l,e.nodeType?[e]:e);else if(ca.test(e)){f=f||k.appendChild(b.createElement("div")),g=(ba.exec(e)||["",""])[1].toLowerCase(),h=ia[g]||ia._default,f.innerHTML=h[1]+e.replace(aa,"<$1>")+h[2],j=h[0];while(j--)f=f.lastChild;n.merge(l,f.childNodes),f=k.firstChild,f.textContent=""}else l.push(b.createTextNode(e));k.textContent="",m=0;while(e=l[m++])if((!d||-1===n.inArray(e,d))&&(i=n.contains(e.ownerDocument,e),f=oa(k.appendChild(e),"script"),i&&ma(f),c)){j=0;while(e=f[j++])fa.test(e.type||"")&&c.push(e)}return k},cleanData:function(a){for(var b,c,d,e,f=n.event.special,g=0;void 0!==(c=a[g]);g++){if(n.acceptData(c)&&(e=c[L.expando],e&&(b=L.cache[e]))){if(b.events)for(d in b.events)f[d]?n.event.remove(c,d):n.removeEvent(c,d,b.handle);L.cache[e]&&delete L.cache[e]}delete M.cache[c[M.expando]]}}}),n.fn.extend({text:function(a){return J(this,function(a){return void 0===a?n.text(this):this.empty().each(function(){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&(this.textContent=a)})},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=ja(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=ja(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?n.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||n.cleanData(oa(c)),c.parentNode&&(b&&n.contains(c.ownerDocument,c)&&ma(oa(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(n.cleanData(oa(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return J(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!da.test(a)&&!ia[(ba.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(aa,"<$1>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(oa(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,n.cleanData(oa(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,l=this.length,m=this,o=l-1,p=a[0],q=n.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&ea.test(p))return this.each(function(c){var d=m.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(c=n.buildFragment(a,this[0].ownerDocument,!1,this),d=c.firstChild,1===c.childNodes.length&&(c=d),d)){for(f=n.map(oa(c,"script"),ka),g=f.length;l>j;j++)h=c,j!==o&&(h=n.clone(h,!0,!0),g&&n.merge(f,oa(h,"script"))),b.call(this[j],h,j);if(g)for(i=f[f.length-1].ownerDocument,n.map(f,la),j=0;g>j;j++)h=f[j],fa.test(h.type||"")&&!L.access(h,"globalEval")&&n.contains(i,h)&&(h.src?n._evalUrl&&n._evalUrl(h.src):n.globalEval(h.textContent.replace(ha,"")))}return this}}),n.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){n.fn[a]=function(a){for(var c,d=[],e=n(a),g=e.length-1,h=0;g>=h;h++)c=h===g?this:this.clone(!0),n(e[h])[b](c),f.apply(d,c.get());return this.pushStack(d)}});var qa,ra={};function sa(b,c){var d,e=n(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:n.css(e[0],"display");return e.detach(),f}function ta(a){var b=l,c=ra[a];return c||(c=sa(a,b),"none"!==c&&c||(qa=(qa||n("