├── .github ├── ISSUE_TEMPLATE │ ├── Bug_Report.yml │ ├── Feature_Request.yml │ └── config.yml └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── .gitmodules ├── CMakeLists.txt ├── CMakePresets.json ├── LICENSE ├── README.md ├── beacon ├── CMakeLists.txt ├── DllMain.cpp ├── beacon.vcxproj ├── beacon.vcxproj.filters ├── beacon_layer.cpp ├── export.def ├── loader.c ├── loader.h └── tbd.h ├── beacondbg.sln ├── bofpack ├── bof_pack.cpp ├── bof_pack.h ├── bofpack.vcxproj ├── bofpack.vcxproj.filters └── main.cpp ├── include ├── beacon.h ├── beacondbg.h ├── cli.h ├── config.h ├── include.vcxitems ├── include.vcxitems.filters └── tclap │ ├── Arg.h │ ├── ArgException.h │ ├── ArgTraits.h │ ├── CmdLine.h │ ├── CmdLineInterface.h │ ├── CmdLineOutput.h │ ├── Constraint.h │ ├── DocBookOutput.h │ ├── HelpVisitor.h │ ├── IgnoreRestVisitor.h │ ├── Makefile.am │ ├── Makefile.in │ ├── MultiArg.h │ ├── MultiSwitchArg.h │ ├── OptionalUnlabeledTracker.h │ ├── StandardTraits.h │ ├── StdOutput.h │ ├── SwitchArg.h │ ├── UnlabeledMultiArg.h │ ├── UnlabeledValueArg.h │ ├── ValueArg.h │ ├── ValuesConstraint.h │ ├── VersionVisitor.h │ ├── Visitor.h │ ├── XorHandler.h │ ├── ZshCompletionOutput.h │ └── sstream.h ├── src ├── beacon_data.h ├── beacondbg.cpp ├── beacondbg.vcxproj ├── beacondbg.vcxproj.filters ├── cli │ ├── args.cpp │ ├── args.h │ ├── breakpoints.cpp │ ├── breakpoints.h │ ├── cli.cpp │ ├── clicmd.cpp │ ├── clicmd.h │ ├── disasm.cpp │ ├── disasm.h │ ├── load.cpp │ ├── load.h │ ├── quit.cpp │ ├── quit.h │ ├── run.cpp │ ├── run.h │ ├── sym.cpp │ └── sym.h ├── disassemble.cpp └── main.cpp ├── static └── disasm.png ├── tests ├── printf.c ├── tests.vcxproj └── tests.vcxproj.filters └── vcpkg.json /.github/ISSUE_TEMPLATE/Bug_Report.yml: -------------------------------------------------------------------------------- 1 | name: "Bug report 🐛" 2 | description: Report errors or unexpected behavior 3 | labels: [Issue-Bug, Needs-Triage] 4 | # type: Bug 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: | 9 | Please make sure to [search for existing issues](https://github.com/wolfcod/beacondbg/issues) and [check the FAQ](https://github.com/wolfcod/beacondbg/wiki/Frequently-Asked-Questions-(FAQ)) before filing a new one! 10 | 11 | If this is an application crash, please also provide the BOF source code. 12 | 13 | - type: input 14 | attributes: 15 | label: beacondbg Version 16 | placeholder: "0.1.0" 17 | description: | 18 | You can copy the version number from the beacondbg version. 19 | validations: 20 | required: false 21 | 22 | - type: input 23 | attributes: 24 | label: Windows build number 25 | placeholder: "10.0.22621.0" 26 | description: | 27 | Please run `ver` or `[Environment]::OSVersion`. 28 | validations: 29 | required: false 30 | 31 | - type: textarea 32 | attributes: 33 | label: Other Software 34 | description: If you're reporting a bug about our interaction with other software, what software? What versions? 35 | placeholder: | 36 | beacondbg v0.1.0 (include a code snippet if it would help!) 37 | validations: 38 | required: false 39 | 40 | - type: textarea 41 | attributes: 42 | label: Steps to reproduce 43 | placeholder: Tell us the steps required to trigger your bug. 44 | validations: 45 | required: true 46 | 47 | - type: textarea 48 | attributes: 49 | label: Expected Behavior 50 | description: If you want to include screenshots, paste them into the markdown editor below. 51 | placeholder: What were you expecting? 52 | validations: 53 | required: false 54 | 55 | - type: textarea 56 | attributes: 57 | label: Actual Behavior 58 | placeholder: What happened instead? 59 | validations: 60 | required: true 61 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/Feature_Request.yml: -------------------------------------------------------------------------------- 1 | name: "Feature Request/Idea 🚀" 2 | description: Suggest a new feature or improvement (this does not mean you have to implement it) 3 | labels: [Issue-Feature] 4 | body: 5 | - type: textarea 6 | attributes: 7 | label: Description of the new feature 8 | description: A clear and concise description of what the problem is that the new feature would solve. 9 | placeholder: | 10 | ... I want to. 11 | validations: 12 | required: true 13 | 14 | - type: textarea 15 | attributes: 16 | label: Proposed technical implementation details 17 | description: This field is optional. If you have any ideas, let us know! 18 | validations: 19 | required: false 20 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: true 2 | 3 | contact_links: 4 | - name: beacondbg 🔐 5 | url: https://github.com/wolfcod/beacondbg/issues/new?Bug_Report.yml 6 | about: Please report bug/security vulnerabilities here. 7 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Summary of the Pull Request 2 | 3 | ## References and Relevant Issues 4 | 5 | ## Detailed Description of the Pull Request / Additional comments 6 | 7 | ## Validation Steps Performed 8 | 9 | ## PR Checklist 10 | - [ ] Closes #xxx 11 | - [ ] Tests added/passed 12 | - [ ] Documentation updated 13 | - If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx 14 | - [ ] Schema updated (if necessary) 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Mono auto generated files 17 | mono_crash.* 18 | 19 | # Build results 20 | [Bb]uild/ 21 | [Dd]ebug/ 22 | [Dd]ebugPublic/ 23 | [Rr]elease/ 24 | [Rr]eleases/ 25 | x64/ 26 | x86/ 27 | [Ww][Ii][Nn]32/ 28 | [Aa][Rr][Mm]/ 29 | [Aa][Rr][Mm]64/ 30 | bld/ 31 | [Bb]in/ 32 | [Oo]bj/ 33 | [Ll]og/ 34 | [Ll]ogs/ 35 | 36 | # Visual Studio 2015/2017 cache/options directory 37 | .vs/ 38 | # Uncomment if you have tasks that create the project's static files in wwwroot 39 | #wwwroot/ 40 | 41 | # Visual Studio 2017 auto generated files 42 | Generated\ Files/ 43 | 44 | # MSTest test Results 45 | [Tt]est[Rr]esult*/ 46 | [Bb]uild[Ll]og.* 47 | 48 | # NUnit 49 | *.VisualState.xml 50 | TestResult.xml 51 | nunit-*.xml 52 | 53 | # Build Results of an ATL Project 54 | [Dd]ebugPS/ 55 | [Rr]eleasePS/ 56 | dlldata.c 57 | 58 | # Benchmark Results 59 | BenchmarkDotNet.Artifacts/ 60 | 61 | # .NET Core 62 | project.lock.json 63 | project.fragment.lock.json 64 | artifacts/ 65 | 66 | # ASP.NET Scaffolding 67 | ScaffoldingReadMe.txt 68 | 69 | # StyleCop 70 | StyleCopReport.xml 71 | 72 | # Files built by Visual Studio 73 | *_i.c 74 | *_p.c 75 | *_h.h 76 | *.ilk 77 | *.meta 78 | *.obj 79 | *.iobj 80 | *.pch 81 | *.pdb 82 | *.ipdb 83 | *.pgc 84 | *.pgd 85 | *.rsp 86 | *.sbr 87 | *.tlb 88 | *.tli 89 | *.tlh 90 | *.tmp 91 | *.tmp_proj 92 | *_wpftmp.csproj 93 | *.log 94 | *.tlog 95 | *.vspscc 96 | *.vssscc 97 | .builds 98 | *.pidb 99 | *.svclog 100 | *.scc 101 | 102 | # Chutzpah Test files 103 | _Chutzpah* 104 | 105 | # Visual C++ cache files 106 | ipch/ 107 | *.aps 108 | *.ncb 109 | *.opendb 110 | *.opensdf 111 | *.sdf 112 | *.cachefile 113 | *.VC.db 114 | *.VC.VC.opendb 115 | 116 | # Visual Studio profiler 117 | *.psess 118 | *.vsp 119 | *.vspx 120 | *.sap 121 | 122 | # Visual Studio Trace Files 123 | *.e2e 124 | 125 | # TFS 2012 Local Workspace 126 | $tf/ 127 | 128 | # Guidance Automation Toolkit 129 | *.gpState 130 | 131 | # ReSharper is a .NET coding add-in 132 | _ReSharper*/ 133 | *.[Rr]e[Ss]harper 134 | *.DotSettings.user 135 | 136 | # TeamCity is a build add-in 137 | _TeamCity* 138 | 139 | # DotCover is a Code Coverage Tool 140 | *.dotCover 141 | 142 | # AxoCover is a Code Coverage Tool 143 | .axoCover/* 144 | !.axoCover/settings.json 145 | 146 | # Coverlet is a free, cross platform Code Coverage Tool 147 | coverage*.json 148 | coverage*.xml 149 | coverage*.info 150 | 151 | # Visual Studio code coverage results 152 | *.coverage 153 | *.coveragexml 154 | 155 | # NCrunch 156 | _NCrunch_* 157 | .*crunch*.local.xml 158 | nCrunchTemp_* 159 | 160 | # MightyMoose 161 | *.mm.* 162 | AutoTest.Net/ 163 | 164 | # Web workbench (sass) 165 | .sass-cache/ 166 | 167 | # Installshield output folder 168 | [Ee]xpress/ 169 | 170 | # DocProject is a documentation generator add-in 171 | DocProject/buildhelp/ 172 | DocProject/Help/*.HxT 173 | DocProject/Help/*.HxC 174 | DocProject/Help/*.hhc 175 | DocProject/Help/*.hhk 176 | DocProject/Help/*.hhp 177 | DocProject/Help/Html2 178 | DocProject/Help/html 179 | 180 | # Click-Once directory 181 | publish/ 182 | 183 | # Publish Web Output 184 | *.[Pp]ublish.xml 185 | *.azurePubxml 186 | # Note: Comment the next line if you want to checkin your web deploy settings, 187 | # but database connection strings (with potential passwords) will be unencrypted 188 | *.pubxml 189 | *.publishproj 190 | 191 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 192 | # checkin your Azure Web App publish settings, but sensitive information contained 193 | # in these scripts will be unencrypted 194 | PublishScripts/ 195 | 196 | # NuGet Packages 197 | *.nupkg 198 | # NuGet Symbol Packages 199 | *.snupkg 200 | # The packages folder can be ignored because of Package Restore 201 | **/[Pp]ackages/* 202 | # except build/, which is used as an MSBuild target. 203 | !**/[Pp]ackages/build/ 204 | # Uncomment if necessary however generally it will be regenerated when needed 205 | #!**/[Pp]ackages/repositories.config 206 | # NuGet v3's project.json files produces more ignorable files 207 | *.nuget.props 208 | *.nuget.targets 209 | 210 | # Microsoft Azure Build Output 211 | csx/ 212 | *.build.csdef 213 | 214 | # Microsoft Azure Emulator 215 | ecf/ 216 | rcf/ 217 | 218 | # Windows Store app package directories and files 219 | AppPackages/ 220 | BundleArtifacts/ 221 | Package.StoreAssociation.xml 222 | _pkginfo.txt 223 | *.appx 224 | *.appxbundle 225 | *.appxupload 226 | 227 | # Visual Studio cache files 228 | # files ending in .cache can be ignored 229 | *.[Cc]ache 230 | # but keep track of directories ending in .cache 231 | !?*.[Cc]ache/ 232 | 233 | # Others 234 | ClientBin/ 235 | ~$* 236 | *~ 237 | *.dbmdl 238 | *.dbproj.schemaview 239 | *.jfm 240 | *.pfx 241 | *.publishsettings 242 | orleans.codegen.cs 243 | 244 | # Including strong name files can present a security risk 245 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 246 | #*.snk 247 | 248 | # Since there are multiple workflows, uncomment next line to ignore bower_components 249 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 250 | #bower_components/ 251 | 252 | # RIA/Silverlight projects 253 | Generated_Code/ 254 | 255 | # Backup & report files from converting an old project file 256 | # to a newer Visual Studio version. Backup files are not needed, 257 | # because we have git ;-) 258 | _UpgradeReport_Files/ 259 | Backup*/ 260 | UpgradeLog*.XML 261 | UpgradeLog*.htm 262 | ServiceFabricBackup/ 263 | *.rptproj.bak 264 | 265 | # SQL Server files 266 | *.mdf 267 | *.ldf 268 | *.ndf 269 | 270 | # Business Intelligence projects 271 | *.rdl.data 272 | *.bim.layout 273 | *.bim_*.settings 274 | *.rptproj.rsuser 275 | *- [Bb]ackup.rdl 276 | *- [Bb]ackup ([0-9]).rdl 277 | *- [Bb]ackup ([0-9][0-9]).rdl 278 | 279 | # Microsoft Fakes 280 | FakesAssemblies/ 281 | 282 | # GhostDoc plugin setting file 283 | *.GhostDoc.xml 284 | 285 | # Node.js Tools for Visual Studio 286 | .ntvs_analysis.dat 287 | node_modules/ 288 | 289 | # Visual Studio 6 build log 290 | *.plg 291 | 292 | # Visual Studio 6 workspace options file 293 | *.opt 294 | 295 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 296 | *.vbw 297 | 298 | # Visual Studio 6 auto-generated project file (contains which files were open etc.) 299 | *.vbp 300 | 301 | # Visual Studio 6 workspace and project file (working project files containing files to include in project) 302 | *.dsw 303 | *.dsp 304 | 305 | # Visual Studio 6 technical files 306 | *.ncb 307 | *.aps 308 | 309 | # Visual Studio LightSwitch build output 310 | **/*.HTMLClient/GeneratedArtifacts 311 | **/*.DesktopClient/GeneratedArtifacts 312 | **/*.DesktopClient/ModelManifest.xml 313 | **/*.Server/GeneratedArtifacts 314 | **/*.Server/ModelManifest.xml 315 | _Pvt_Extensions 316 | 317 | # Paket dependency manager 318 | .paket/paket.exe 319 | paket-files/ 320 | 321 | # FAKE - F# Make 322 | .fake/ 323 | 324 | # CodeRush personal settings 325 | .cr/personal 326 | 327 | # Python Tools for Visual Studio (PTVS) 328 | __pycache__/ 329 | *.pyc 330 | 331 | # Cake - Uncomment if you are using it 332 | # tools/** 333 | # !tools/packages.config 334 | 335 | # Tabs Studio 336 | *.tss 337 | 338 | # Telerik's JustMock configuration file 339 | *.jmconfig 340 | 341 | # BizTalk build output 342 | *.btp.cs 343 | *.btm.cs 344 | *.odx.cs 345 | *.xsd.cs 346 | 347 | # OpenCover UI analysis results 348 | OpenCover/ 349 | 350 | # Azure Stream Analytics local run output 351 | ASALocalRun/ 352 | 353 | # MSBuild Binary and Structured Log 354 | *.binlog 355 | 356 | # NVidia Nsight GPU debugger configuration file 357 | *.nvuser 358 | 359 | # MFractors (Xamarin productivity tool) working folder 360 | .mfractor/ 361 | 362 | # Local History for Visual Studio 363 | .localhistory/ 364 | 365 | # Visual Studio History (VSHistory) files 366 | .vshistory/ 367 | 368 | # BeatPulse healthcheck temp database 369 | healthchecksdb 370 | 371 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 372 | MigrationBackup/ 373 | 374 | # Ionide (cross platform F# VS Code tools) working folder 375 | .ionide/ 376 | 377 | # Fody - auto-generated XML schema 378 | FodyWeavers.xsd 379 | 380 | # VS Code files for those working on multiple tools 381 | .vscode/* 382 | !.vscode/settings.json 383 | !.vscode/tasks.json 384 | !.vscode/launch.json 385 | !.vscode/extensions.json 386 | *.code-workspace 387 | 388 | # Local History for Visual Studio Code 389 | .history/ 390 | 391 | # Windows Installer files from build outputs 392 | *.cab 393 | *.msi 394 | *.msix 395 | *.msm 396 | *.msp 397 | 398 | # JetBrains Rider 399 | *.sln.iml 400 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "deps/zydis"] 2 | path = deps/zydis 3 | url = https://github.com/zyantific/zydis/ 4 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | 3 | project(beacondbg) 4 | 5 | if (MSVC) 6 | else() 7 | endif() 8 | 9 | include_directories(include) 10 | 11 | add_definitions(-D_UNICODE -DUNICODE) 12 | add_subdirectory(cli) 13 | # add_subdirectory(coff) 14 | 15 | set(SOURCES src/main.cpp src/beacondbg.cpp) 16 | 17 | 18 | set(CMAKE_CXX_STANDARD 17) 19 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 20 | set(CMAKE_CXX_EXTENSIONS OFF) 21 | 22 | add_executable(beacondbg ${SOURCES}) 23 | 24 | add_dependencies(beacondbg beaconcli) 25 | target_link_libraries(beacondbg beaconcli) 26 | -------------------------------------------------------------------------------- /CMakePresets.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "configurePresets": [ 4 | { 5 | "name": "vcpkg", 6 | "generator": "Ninja", 7 | "binaryDir": "${sourceDir}/build", 8 | "cacheVariables": { 9 | "CMAKE_TOOLCHAIN_FILE": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" 10 | } 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 cod 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # beacondbg 2 | 3 | ***NOTE*** 4 | I'm working on this project in my free time.. i'm trying to integrate [FTXUI](https://github.com/ArthurSonzogni/FTXUI) to improve the the interaction with this project.. but it takes me times because I never used. 5 | 6 | CMAKE file right now it doesn't work.. still using VS 2022 CE for development, but I will switch as soon to CMAKE (so it will be possible to build from your cmdline). 7 | 8 | ***Breakpoint*** 9 | It's almost impossible to debug a single thread inside the same application, without playing with thread context, trace flags and VEH.. The only support available is via Windows Debug API (available for a process), so, I'm isolating the `beacon` outside `beacondbg` to be able to inject into a remote process and to control the debugging experience via RPC, for now it's only in local process via direct call. 10 | 11 | 12 | This is a simple debugger to test/debug a Cobalt Strike beacon without using Cobalt Strike. 13 | Some APIs accessed directly from the beacon are monitored (to track the beacon memory allocation, thread creation etc.). 14 | 15 | The beacon is injected directly into the memory of the beacondbg (in the current version) so, before running any unknown code on your system be aware of risks (***you'll do under your responsability!***). 16 | 17 | ## Disassemble 18 | The disassemble engine is provided by Zydis. Don't forget to clone submodule via 19 | ```shell 20 | git clone --recurse-submodules https://github.com/wolfcod/beacondbg.git 21 | ``` 22 | 23 | After you loaded a module in memory, you can use `sym` command to enumerate symbols (only static functions). 24 | ![image](./static/disasm.png) 25 | 26 | ## How to use 27 | ```shell 28 | ~ ./beacondbg 29 | beacondbg> load yourbeacon.obj 30 | beacondbg> run entrypoint 31 | ``` 32 | 33 | # TO BE IMPLEMENTED 34 | Cobalt Strike Beacons are encoded in a binary sequence extracted through `BeaconDataParse`and underlying APIs. 35 | 36 | Supported Data: 37 | - strings: "This is a simple string" 38 | - unicode strings: L"This is a simple unicode string" 39 | - integers: 1111 or 0x11111 40 | - shorts: 1111s or 0x11111s 41 | - buffer: b"sequence of bytes" 42 | 43 | From command line: 44 | - --integer value 45 | - --short value 46 | - --ascii "string" 47 | - --unicode "unicode string" 48 | - --hex hexdump as argument 49 | - --in input file as argument 50 | 51 | - --output save arguments in an output file 52 | - --input use file as input for arguments 53 | 54 | - --beacon beacon to debug/emulate 55 | 56 | The generation of arguments can be done via `bofpack` tool included in the repo. 57 | 58 | ## Debugger command 59 | - .load: Load a beacon (OBJ file) in memory 60 | - args: Set arguments for the beacon "strings", L"unicode" h"hexdump" b"file as input" sNUMBER iNUMBER 61 | - bp: Normal breakpoint (actually, set a break only on Windows API) 62 | - bl: List of breakpoints 63 | - bc: Clear a breakpoint 64 | - g: continue (or run) 65 | - k: stack trace 66 | - r: registers 67 | - d: Data dump 68 | 69 | ## Components 70 | - [Templatized C++ Command Line Parser](https://tclap.sourceforge.net) 71 | - [Cobalt Strike Beacon Header](https://github.com/Cobalt-Strike/bof_template/blob/main/beacon.h) 72 | - beacon: Emulate the beacon engine.. which can be injected locally or remote 73 | 74 | ## Output 75 | The beacon output is directly printed on your prompt. 76 | If you need to test a beacon which requires admin privileges, you need to run `beacondbg` with admin privileges, or to run a beacon to gain more privileges before running the final beacon. 77 | 78 | ## Notes 79 | 80 | COFFLoader (coff directory) for speeding up the process are Copyright of [trustedsec](https://trustedsec.com). 81 | The original source code is available on [GitHub](https://github.com/trustedsec/COFFLoader).\ 82 | 83 | The source code is distributed to create a MOCK of this project. 84 | -------------------------------------------------------------------------------- /beacon/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | 3 | project(coffloader) 4 | 5 | if (MSVC) 6 | else() 7 | endif() 8 | 9 | include_directories(../include) 10 | 11 | add_definitions(-D_UNICODE -DUNICODE) 12 | 13 | set(CMAKE_CXX_STANDARD 17) 14 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 15 | set(CMAKE_CXX_EXTENSIONS OFF) 16 | 17 | set(SOURCES loader.c) 18 | add_library(coffloader STATIC ${SOURCES}) -------------------------------------------------------------------------------- /beacon/DllMain.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "loader.h" 5 | #include "tbd.h" 6 | 7 | BOOL WINAPI DllMain( 8 | HINSTANCE hinstDLL, // handle to DLL module 9 | DWORD fdwReason, // reason for calling function 10 | LPVOID lpvReserved) // reserved 11 | { 12 | switch (fdwReason) { 13 | case DLL_PROCESS_ATTACH: 14 | break; 15 | case DLL_PROCESS_DETACH: 16 | break; 17 | case DLL_THREAD_ATTACH: 18 | break; 19 | case DLL_THREAD_DETACH: 20 | break; 21 | } 22 | 23 | return TRUE; 24 | } 25 | 26 | 27 | static DWORD WINAPI ThreadBeacon(LPVOID lpParameter) 28 | { 29 | LPTBD tbd = (LPTBD)lpParameter; 30 | 31 | TlsSetValue(0, (LPVOID)tbd); 32 | 33 | int r = RunCOFF((bof_fd*)tbd->hBeacon, (char*)tbd->lpProcName, (unsigned char*)tbd->lpData, (int)tbd->Size); 34 | 35 | CloseHandle(tbd->hThread); 36 | return 0; 37 | } 38 | 39 | BOOL WINAPI RunBeacon(HANDLE hBeacon, LPCSTR lpProcName, LPVOID lpData, SIZE_T Size) 40 | { 41 | if (hBeacon != NULL) { 42 | LPTBD tbd = (LPTBD)calloc(1, sizeof(TBD)); 43 | if (tbd != NULL) { 44 | tbd->hBeacon = hBeacon; 45 | tbd->lpProcName = _strdup(lpProcName); 46 | tbd->lpData = (lpData != NULL) ? malloc(Size) : NULL; 47 | tbd->Size = Size; 48 | if (tbd->lpData != NULL) { 49 | memcpy(tbd->lpData, lpData, Size); 50 | } 51 | DWORD dwThreadId = 0; 52 | HANDLE hBeaconThread = CreateThread(NULL, 0, ThreadBeacon, (LPVOID)tbd, 0, &dwThreadId); 53 | bof_fd* beacon = (bof_fd*)hBeacon; 54 | tbd->hThread = hBeaconThread; 55 | tbd->dwThreadId = dwThreadId; 56 | } 57 | 58 | return tbd != NULL; 59 | } 60 | 61 | return FALSE; 62 | } 63 | 64 | HANDLE WINAPI LoadBeacon(LPVOID lpAddress, SIZE_T Size) 65 | { 66 | bof_fd *beacon = load_bof((unsigned char*)lpAddress, (uint32_t)Size); 67 | 68 | return (HANDLE)beacon;; 69 | } 70 | 71 | BOOL WINAPI CloseBeacon(HANDLE hBeacon) 72 | { 73 | if (hBeacon != NULL) 74 | { 75 | remove_bof((bof_fd*)hBeacon); 76 | return TRUE; 77 | } 78 | 79 | return FALSE; 80 | } 81 | 82 | 83 | BOOL WINAPI FindNextSymbol(HANDLE hBeacon, LPCSTR* lpSymbolName, LPVOID* Address) 84 | { 85 | bof_fd* beacon = (bof_fd*)hBeacon; 86 | 87 | uint32_t tempcounter; 88 | struct coff_sym* coff_sym_ptr = (struct coff_sym*)(beacon->coff_data + beacon->coff_header_ptr->PointerToSymbolTable); 89 | 90 | for (tempcounter = beacon->symbol_position; tempcounter < beacon->coff_header_ptr->NumberOfSymbols; tempcounter++) { 91 | if (coff_sym_ptr[tempcounter].StorageClass != 2) { 92 | beacon->symbol_position++; 93 | continue; 94 | } 95 | 96 | if (coff_sym_ptr[tempcounter].first.value[0] == 0) { 97 | uint32_t e_offset = coff_sym_ptr[tempcounter].first.value[1]; 98 | uint8_t* str_table = (uint8_t *) & coff_sym_ptr[beacon->coff_header_ptr->NumberOfSymbols]; 99 | uint32_t str_size = *((uint32_t*)str_table); 100 | *lpSymbolName = (LPCSTR)(str_table + e_offset); 101 | 102 | } 103 | else { 104 | *lpSymbolName = (coff_sym_ptr[tempcounter].first.Name); 105 | } 106 | 107 | if (coff_sym_ptr[tempcounter].SectionNumber == 0xffff) { 108 | *Address = NULL; 109 | } 110 | else { 111 | *Address = (LPVOID)((ULONG_PTR)beacon->sectionMapping[coff_sym_ptr[tempcounter].SectionNumber - 1] + coff_sym_ptr[tempcounter].Value); 112 | } 113 | beacon->symbol_position++; 114 | return TRUE; 115 | } 116 | 117 | return FALSE; 118 | } 119 | 120 | BOOL WINAPI FindFirstSymbol(HANDLE hBeacon, LPCSTR* lpSymbolName, LPVOID* Address) 121 | { 122 | if (hBeacon == NULL) { 123 | *lpSymbolName = NULL; 124 | *Address = NULL; 125 | return FALSE; 126 | } 127 | 128 | bof_fd* beacon = (bof_fd *)hBeacon; 129 | beacon->symbol_position = 0; 130 | return FindNextSymbol(hBeacon, lpSymbolName, Address); 131 | } 132 | 133 | BOOL WINAPI ClearBreakPoint() 134 | { 135 | return FALSE; 136 | } 137 | 138 | BOOL WINAPI SetBreakPoint() 139 | { 140 | return FALSE; 141 | } -------------------------------------------------------------------------------- /beacon/beacon.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 17.0 23 | Win32Proj 24 | {b3d986bd-e08f-4f42-ad5a-dc650406f47a} 25 | beacon 26 | 10.0 27 | 28 | 29 | 30 | DynamicLibrary 31 | true 32 | v143 33 | Unicode 34 | 35 | 36 | DynamicLibrary 37 | false 38 | v143 39 | true 40 | Unicode 41 | 42 | 43 | DynamicLibrary 44 | true 45 | v143 46 | Unicode 47 | 48 | 49 | DynamicLibrary 50 | false 51 | v143 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | $(SolutionDir)build\ 75 | $(SolutionDir)build\$(ProjectName)\ 76 | 77 | 78 | $(SolutionDir)build\ 79 | $(SolutionDir)build\$(ProjectName)\ 80 | 81 | 82 | $(SolutionDir)build\ 83 | $(SolutionDir)build\$(ProjectName)\ 84 | $(SolutionDir)include\;$(VC_IncludePath);$(WindowsSDK_IncludePath); 85 | 86 | 87 | $(SolutionDir)build\ 88 | $(SolutionDir)build\$(ProjectName)\ 89 | $(SolutionDir)include\;l$(VC_IncludePath);$(WindowsSDK_IncludePath) 90 | 91 | 92 | 93 | Level3 94 | true 95 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 96 | true 97 | 98 | 99 | Console 100 | true 101 | export.def 102 | 103 | 104 | 105 | 106 | Level3 107 | true 108 | true 109 | true 110 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 111 | true 112 | 113 | 114 | Console 115 | true 116 | true 117 | true 118 | export.def 119 | 120 | 121 | 122 | 123 | Level3 124 | true 125 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 126 | true 127 | 128 | 129 | Console 130 | true 131 | $(OutDir)coff.lib;$(CoreLibraryDependencies);%(AdditionalDependencies) 132 | export.def 133 | 134 | 135 | 136 | 137 | Level3 138 | true 139 | true 140 | true 141 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 142 | true 143 | MultiThreaded 144 | 145 | 146 | Console 147 | true 148 | true 149 | false 150 | $(OutDir)coff.lib;$(CoreLibraryDependencies);%(AdditionalDependencies) 151 | export.def 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | -------------------------------------------------------------------------------- /beacon/beacon.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | Source Files 26 | 27 | 28 | 29 | 30 | Source Files 31 | 32 | 33 | 34 | 35 | Header Files 36 | 37 | 38 | Header Files 39 | 40 | 41 | -------------------------------------------------------------------------------- /beacon/export.def: -------------------------------------------------------------------------------- 1 | LIBRARY beacon 2 | 3 | EXPORTS 4 | RunBeacon 5 | LoadBeacon 6 | CloseBeacon 7 | 8 | FindFirstSymbol 9 | FindNextSymbol 10 | SetBreakPoint -------------------------------------------------------------------------------- /beacon/loader.h: -------------------------------------------------------------------------------- 1 | #ifndef COFFLOADER_H_ 2 | #define COFFLOADER_H_ 3 | #include 4 | #include 5 | 6 | /* These seem to be the same sizes across architectures, relocations are different though. Defined both sets of types. */ 7 | 8 | /* sizeof 20 */ 9 | typedef struct coff_file_header { 10 | uint16_t Machine; 11 | uint16_t NumberOfSections; 12 | uint32_t TimeDateStamp; 13 | uint32_t PointerToSymbolTable; 14 | uint32_t NumberOfSymbols; 15 | uint16_t SizeOfOptionalHeader; 16 | uint16_t Characteristics; 17 | } coff_file_header_t; 18 | 19 | /* AMD64 should always be here */ 20 | #define MACHINETYPE_AMD64 0x8664 21 | 22 | #ifdef _MSC_VER 23 | #pragma pack(push,1) 24 | #else 25 | #endif 26 | 27 | /* Size of 40 */ 28 | typedef struct coff_sect { 29 | char Name[8]; 30 | uint32_t VirtualSize; 31 | uint32_t VirtualAddress; 32 | uint32_t SizeOfRawData; 33 | uint32_t PointerToRawData; 34 | uint32_t PointerToRelocations; 35 | uint32_t PointerToLineNumbers; 36 | uint16_t NumberOfRelocations; 37 | uint16_t NumberOfLinenumbers; 38 | uint32_t Characteristics; 39 | } coff_sect_t; 40 | 41 | 42 | typedef struct coff_reloc { 43 | uint32_t VirtualAddress; 44 | uint32_t SymbolTableIndex; 45 | uint16_t Type; 46 | } coff_reloc_t; 47 | 48 | typedef struct coff_sym { 49 | union { 50 | char Name[8]; 51 | uint32_t value[2]; 52 | } first; 53 | uint32_t Value; 54 | uint16_t SectionNumber; 55 | uint16_t Type; 56 | uint8_t StorageClass; 57 | uint8_t NumberOfAuxSymbols; 58 | 59 | } coff_sym_t; 60 | 61 | #ifdef _MSC_VER 62 | #pragma pack(pop) 63 | #endif 64 | 65 | /* AMD64 Specific types */ 66 | #define IMAGE_REL_AMD64_ABSOLUTE 0x0000 67 | #define IMAGE_REL_AMD64_ADDR64 0x0001 68 | #define IMAGE_REL_AMD64_ADDR32 0x0002 69 | #define IMAGE_REL_AMD64_ADDR32NB 0x0003 70 | /* Most common from the looks of it, just 32-bit relative address from the byte following the relocation */ 71 | #define IMAGE_REL_AMD64_REL32 0x0004 72 | /* Second most common, 32-bit address without an image base. Not sure what that means... */ 73 | #define IMAGE_REL_AMD64_REL32_1 0x0005 74 | #define IMAGE_REL_AMD64_REL32_2 0x0006 75 | #define IMAGE_REL_AMD64_REL32_3 0x0007 76 | #define IMAGE_REL_AMD64_REL32_4 0x0008 77 | #define IMAGE_REL_AMD64_REL32_5 0x0009 78 | #define IMAGE_REL_AMD64_SECTION 0x000A 79 | #define IMAGE_REL_AMD64_SECREL 0x000B 80 | #define IMAGE_REL_AMD64_SECREL7 0x000C 81 | #define IMAGE_REL_AMD64_TOKEN 0x000D 82 | #define IMAGE_REL_AMD64_SREL32 0x000E 83 | #define IMAGE_REL_AMD64_PAIR 0x000F 84 | #define IMAGE_REL_AMD64_SSPAN32 0x0010 85 | 86 | /*i386 Relocation types */ 87 | 88 | #define IMAGE_REL_I386_ABSOLUTE 0x0000 89 | #define IMAGE_REL_I386_DIR16 0x0001 90 | #define IMAGE_REL_I386_REL16 0x0002 91 | #define IMAGE_REL_I386_DIR32 0x0006 92 | #define IMAGE_REL_I386_DIR32NB 0x0007 93 | #define IMAGE_REL_I386_SEG12 0x0009 94 | #define IMAGE_REL_I386_SECTION 0x000A 95 | #define IMAGE_REL_I386_SECREL 0x000B 96 | #define IMAGE_REL_I386_TOKEN 0x000C 97 | #define IMAGE_REL_I386_SECREL7 0x000D 98 | #define IMAGE_REL_I386_REL32 0x0014 99 | 100 | /* Section Characteristic Flags */ 101 | 102 | #define IMAGE_SCN_MEM_WRITE 0x80000000 103 | #define IMAGE_SCN_MEM_READ 0x40000000 104 | #define IMAGE_SCN_MEM_EXECUTE 0x20000000 105 | #define IMAGE_SCN_ALIGN_16BYTES 0x00500000 106 | #define IMAGE_SCN_MEM_NOT_CACHED 0x04000000 107 | #define IMAGE_SCN_MEM_NOT_PAGED 0x08000000 108 | #define IMAGE_SCN_MEM_SHARED 0x10000000 109 | #define IMAGE_SCN_CNT_CODE 0x00000020 110 | #define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080 111 | #define IMAGE_SCN_MEM_DISCARDABLE 0x02000000 112 | 113 | #ifdef __cplusplus 114 | extern "C" { 115 | #endif 116 | 117 | typedef struct _bof_fd 118 | { 119 | char* coff_data; 120 | size_t coff_size; 121 | 122 | struct coff_file_header* coff_header_ptr; 123 | 124 | char** sectionMapping; 125 | 126 | char* functionMapping; 127 | int functionMappingCount; 128 | 129 | DWORD symbol_position; 130 | } bof_fd; 131 | 132 | bof_fd* load_bof(unsigned char* coff_data, uint32_t filesize); 133 | 134 | int RunCOFF(bof_fd *bof, char* functionname, unsigned char* argumentdata, int argumentSize); 135 | int remove_bof(bof_fd* bof); 136 | 137 | unsigned char* unhexlify(unsigned char* value, int *outlen); 138 | #ifdef __cplusplus 139 | } 140 | #endif 141 | 142 | struct BEACON_Functions 143 | { 144 | const char* FunctionName; 145 | unsigned char* FunctionAddress; 146 | DWORD Flags; 147 | }; 148 | /// 149 | #ifdef __cplusplus 150 | extern "C" 151 | #endif 152 | struct BEACON_Functions InternalFunctions[30]; 153 | 154 | #endif 155 | -------------------------------------------------------------------------------- /beacon/tbd.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef __TBD_H_ 4 | #define __TBD_H_ 5 | 6 | typedef struct ThreadBeaconData 7 | { 8 | HANDLE hThread; 9 | DWORD dwThreadId; 10 | 11 | HANDLE hBeacon; 12 | LPCSTR lpProcName; 13 | LPVOID lpData; 14 | SIZE_T Size; 15 | } TBD, *LPTBD; 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /bofpack/bof_pack.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "bof_pack.h" 10 | 11 | template 12 | T bswap(T value) 13 | { 14 | T r = 0; 15 | 16 | for (int i = 0; i < sizeof(T); i++) { 17 | uint8_t n = (uint8_t)value & 0xff; 18 | r |= n << (sizeof(T) - i - 1) * 8; 19 | } 20 | 21 | return r; 22 | } 23 | 24 | bof_pack::bof_pack() 25 | : bof(nullptr), bof_size(0) 26 | { 27 | 28 | } 29 | bof_pack::~bof_pack() 30 | { 31 | if (bof != nullptr) 32 | free(bof); 33 | bof = nullptr; 34 | bof_size = 0; 35 | } 36 | 37 | void bof_pack::append(void* src, size_t size) 38 | { 39 | char* tmp = (char *)realloc(bof, bof_size + size); 40 | if (tmp != nullptr) { 41 | memcpy(tmp + bof_size, src, size); 42 | bof_size += size; 43 | bof = tmp; 44 | } 45 | } 46 | void bof_pack::encodeShort(short value) 47 | { 48 | short n = bswap(value); 49 | 50 | append(&n, sizeof(short)); 51 | } 52 | 53 | void bof_pack::encodeInteger(int value) 54 | { 55 | int n = bswap(value); 56 | 57 | append(&n, sizeof(int)); 58 | } 59 | 60 | void bof_pack::encodeString(const char* str) 61 | { 62 | encodeInteger(strlen(str) + 1); 63 | append((void *)str, strlen(str) + 1); 64 | } 65 | 66 | void bof_pack::encodeWideString(const char* str) 67 | { 68 | char dummy[2] = {}; 69 | 70 | encodeInteger((strlen(str) + 1) * 2); 71 | 72 | for (int i = 0; i < strlen(str); i++) { 73 | dummy[0] = str[i]; dummy[1] = 0; 74 | append(dummy, 2); 75 | } 76 | dummy[0] = 0; dummy[1] = 0; 77 | append(dummy, 2); 78 | } 79 | 80 | bool bof_pack::encodeBinary(const char* inputFile) 81 | { 82 | std::ifstream input(inputFile, std::ios::binary); 83 | 84 | if (!input) { 85 | return false; 86 | } 87 | 88 | std::vector buffer(std::istreambuf_iterator(input), {}); 89 | 90 | encodeInteger((int)buffer.size()); 91 | append(buffer.data(), buffer.size()); 92 | return true; 93 | } 94 | -------------------------------------------------------------------------------- /bofpack/bof_pack.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct bof_pack 4 | { 5 | bof_pack(); 6 | ~bof_pack(); 7 | 8 | void encodeShort(short value); 9 | void encodeInteger(int value); 10 | void encodeString(const char* str); 11 | void encodeWideString(const char* str); 12 | bool encodeBinary(const char* inputFile); 13 | 14 | void append(void* src, size_t size); 15 | 16 | char* bof; 17 | int bof_size; 18 | }; -------------------------------------------------------------------------------- /bofpack/bofpack.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 17.0 23 | Win32Proj 24 | {ef91a684-c3f1-4a0e-a3fa-c75f21b1c631} 25 | bofpack 26 | 10.0 27 | 28 | 29 | 30 | Application 31 | true 32 | v143 33 | Unicode 34 | 35 | 36 | Application 37 | false 38 | v143 39 | true 40 | Unicode 41 | 42 | 43 | Application 44 | true 45 | v143 46 | Unicode 47 | 48 | 49 | Application 50 | false 51 | v143 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | $(SolutionDir)build\ 75 | $(SolutionDir)build\$(ProjectName)\ 76 | $(SolutionDir)include\;$(VC_IncludePath);$(WindowsSDK_IncludePath); 77 | 78 | 79 | $(SolutionDir)build\ 80 | $(SolutionDir)build\$(ProjectName)\ 81 | $(SolutionDir)include\;$(VC_IncludePath);$(WindowsSDK_IncludePath); 82 | 83 | 84 | $(SolutionDir)build\ 85 | $(SolutionDir)build\$(ProjectName)\ 86 | $(SolutionDir)include\;$(VC_IncludePath);$(WindowsSDK_IncludePath); 87 | 88 | 89 | $(SolutionDir)build\ 90 | $(SolutionDir)build\$(ProjectName)\ 91 | $(SolutionDir)include\;$(VC_IncludePath);$(WindowsSDK_IncludePath); 92 | 93 | 94 | 95 | Level3 96 | true 97 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 98 | true 99 | 100 | 101 | Console 102 | true 103 | 104 | 105 | 106 | 107 | Level3 108 | true 109 | true 110 | true 111 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 112 | true 113 | 114 | 115 | Console 116 | true 117 | true 118 | true 119 | 120 | 121 | 122 | 123 | Level3 124 | true 125 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 126 | true 127 | 128 | 129 | Console 130 | true 131 | 132 | 133 | 134 | 135 | Level3 136 | true 137 | true 138 | true 139 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 140 | true 141 | MultiThreaded 142 | 143 | 144 | Console 145 | true 146 | true 147 | true 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | -------------------------------------------------------------------------------- /bofpack/bofpack.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | 26 | 27 | Header Files 28 | 29 | 30 | -------------------------------------------------------------------------------- /bofpack/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "bof_pack.h" 8 | 9 | int main(int argc, char* argv[]) 10 | { 11 | if (argc == 1) { 12 | std::cout << "bofpack -o dst -i integer -s short -b binary file -a \"ascii string\" -w \"wide string\"" << std::endl; 13 | return 0; 14 | } 15 | 16 | bof_pack pack; 17 | 18 | std::string outputFile; 19 | 20 | for (int i = 1; i < argc; i += 2) { 21 | if (argv[i][0] != '-') { 22 | std::cout << "wrong pattern " << argv[i] << std::endl; 23 | return 0; 24 | } 25 | 26 | if (argv[i][1] == 'o') { 27 | outputFile = argv[i + 1]; 28 | } 29 | else if (argv[i][1] == 'i') { 30 | pack.encodeInteger(std::atoi(argv[i + 1])); 31 | } 32 | else if (argv[i][1] == 's') { 33 | pack.encodeShort((short)std::atoi(argv[i + 1])); 34 | } 35 | else if (argv[i][1] == 'a') { 36 | pack.encodeString(argv[i + 1]); 37 | } 38 | else if (argv[i][1] == 'w') { 39 | pack.encodeWideString(argv[i + 1]); 40 | } 41 | else if (argv[i][1] == 'b') { 42 | if (pack.encodeBinary(argv[i + 1]) == false) { 43 | std::cout << "Cannot open " << argv[i + 1] << std::endl; 44 | return 0; 45 | } 46 | } 47 | } 48 | 49 | std::ofstream output(outputFile, std::ios::binary); 50 | 51 | if (!output) { 52 | std::cout << "Error opening " << outputFile << std::endl; 53 | return 0; 54 | } 55 | output.write(pack.bof, pack.bof_size); 56 | 57 | output.close(); 58 | 59 | std::cout << "file generated. Size " << pack.bof_size << " bytes." << std::endl; 60 | return 0; 61 | } -------------------------------------------------------------------------------- /include/beacondbg.h: -------------------------------------------------------------------------------- 1 | #ifndef __BEACONDBG_H_ 2 | #define __BEACONDBG_H_ 3 | 4 | #ifdef __cplusplus 5 | #include 6 | 7 | enum class BeaconError 8 | { 9 | CriticalError, /** beacon.dll not found.. cannot interact with a beacon */ 10 | InvalidArguments, 11 | FileNotFound, 12 | FileNotValid, 13 | EntryPointNotFound, 14 | InvalidAddress, 15 | InvalidStatus, // this command cannot be executed in the current status 16 | none // latest arguments.. everything is fine 17 | }; 18 | 19 | enum class BeaconStatus 20 | { 21 | ready, /* the beacon is ready to accept any commands ... */ 22 | loaded, /* a beacon is loaded */ 23 | running, /* a beacon is running.. so only breakpoints or terminate commands are accepted */ 24 | terminate // the beacon will die 25 | }; 26 | 27 | class beacondbg 28 | { 29 | public: 30 | static beacondbg* create(std::istream &cin, std::ostream &cout); 31 | 32 | public: 33 | ~beacondbg() = default; 34 | 35 | inline void setError(BeaconError value) { this->errorStatus = value; } 36 | inline BeaconError getError() { return this->errorStatus; } 37 | inline void setStatus(BeaconStatus value) { this->beaconStatus = value; } 38 | inline BeaconStatus getStatus() { return this->beaconStatus; } 39 | 40 | /** load a beacon in the debugger */ 41 | bool load(const std::string beaconName, const std::vector &content); 42 | bool loadArgs(const std::vector& content); 43 | bool loadFromFile(const std::string &fileName); 44 | 45 | bool loadBofPack(const std::string& fileName); 46 | 47 | /** unload the beacon from the memory */ 48 | bool unload(const std::string &name); 49 | 50 | /** set a beacon PID used for debugging */ 51 | bool setTargetPid(uint32_t pid); 52 | 53 | bool setBreakPoint(void *address); 54 | bool clearBreakPoint(void *address); 55 | 56 | bool run(std::string entryPoint, std::vector args); 57 | bool disassemble(std::string symbol, std::vector args); 58 | bool enumerateSymbols(); 59 | 60 | void print(const std::string fmt); 61 | void println(const std::string fmt); 62 | void clear(); 63 | void error(const std::string fmt); 64 | std::string readln(); 65 | 66 | bool prompt(); 67 | private: 68 | std::string beaconName_; 69 | int pid; 70 | std::istream ∈ 71 | std::ostream &out; 72 | 73 | private: 74 | beacondbg(std::istream& input, std::ostream& output); 75 | BeaconError errorStatus; 76 | BeaconStatus beaconStatus; 77 | }; 78 | #else 79 | #endif 80 | 81 | #endif -------------------------------------------------------------------------------- /include/cli.h: -------------------------------------------------------------------------------- 1 | #ifndef __BEACON_CLI_H 2 | #define __BEACON_CLI_H 3 | 4 | int cli(beacondbg *emu); 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /include/config.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef __CONFIG_H 4 | #define __CONFIG_H 5 | 6 | #define BEACONDBG_VERSION "0.1" 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /include/include.vcxitems: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(MSBuildAllProjects);$(MSBuildThisFileFullPath) 5 | true 6 | {ec5ee909-1bc1-4ec9-9e60-9fdcabb2ffe6} 7 | 8 | 9 | 10 | %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory) 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /include/include.vcxitems.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {7fba8b3b-b2d9-4c4d-8f51-a5ab13d19048} 6 | 7 | 8 | 9 | 10 | tclap 11 | 12 | 13 | tclap 14 | 15 | 16 | tclap 17 | 18 | 19 | tclap 20 | 21 | 22 | tclap 23 | 24 | 25 | tclap 26 | 27 | 28 | tclap 29 | 30 | 31 | tclap 32 | 33 | 34 | tclap 35 | 36 | 37 | tclap 38 | 39 | 40 | tclap 41 | 42 | 43 | tclap 44 | 45 | 46 | tclap 47 | 48 | 49 | tclap 50 | 51 | 52 | tclap 53 | 54 | 55 | tclap 56 | 57 | 58 | tclap 59 | 60 | 61 | tclap 62 | 63 | 64 | tclap 65 | 66 | 67 | tclap 68 | 69 | 70 | tclap 71 | 72 | 73 | tclap 74 | 75 | 76 | tclap 77 | 78 | 79 | tclap 80 | 81 | 82 | tclap 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | tclap 92 | 93 | 94 | tclap 95 | 96 | 97 | -------------------------------------------------------------------------------- /include/tclap/ArgException.h: -------------------------------------------------------------------------------- 1 | // -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- 2 | 3 | /****************************************************************************** 4 | * 5 | * file: ArgException.h 6 | * 7 | * Copyright (c) 2003, Michael E. Smoot . 8 | * Copyright (c) 2017 Google LLC 9 | * All rights reserved. 10 | * 11 | * See the file COPYING in the top directory of this distribution for 12 | * more information. 13 | * 14 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | * 22 | *****************************************************************************/ 23 | 24 | 25 | #ifndef TCLAP_ARG_EXCEPTION_H 26 | #define TCLAP_ARG_EXCEPTION_H 27 | 28 | #include 29 | #include 30 | 31 | namespace TCLAP { 32 | 33 | /** 34 | * A simple class that defines and argument exception. Should be caught 35 | * whenever a CmdLine is created and parsed. 36 | */ 37 | class ArgException : public std::exception 38 | { 39 | public: 40 | 41 | /** 42 | * Constructor. 43 | * \param text - The text of the exception. 44 | * \param id - The text identifying the argument source. 45 | * \param td - Text describing the type of ArgException it is. 46 | * of the exception. 47 | */ 48 | ArgException( const std::string& text = "undefined exception", 49 | const std::string& id = "undefined", 50 | const std::string& td = "Generic ArgException") 51 | : std::exception(), 52 | _errorText(text), 53 | _argId( id ), 54 | _typeDescription(td) 55 | { } 56 | 57 | /** 58 | * Destructor. 59 | */ 60 | virtual ~ArgException() throw() { } 61 | 62 | /** 63 | * Returns the error text. 64 | */ 65 | std::string error() const { return ( _errorText ); } 66 | 67 | /** 68 | * Returns the argument id. 69 | */ 70 | std::string argId() const 71 | { 72 | if ( _argId == "undefined" ) 73 | return " "; 74 | else 75 | return ( "Argument: " + _argId ); 76 | } 77 | 78 | /** 79 | * Returns the arg id and error text. 80 | */ 81 | const char* what() const throw() 82 | { 83 | static std::string ex; 84 | ex = _argId + " -- " + _errorText; 85 | return ex.c_str(); 86 | } 87 | 88 | /** 89 | * Returns the type of the exception. Used to explain and distinguish 90 | * between different child exceptions. 91 | */ 92 | std::string typeDescription() const 93 | { 94 | return _typeDescription; 95 | } 96 | 97 | 98 | private: 99 | 100 | /** 101 | * The text of the exception message. 102 | */ 103 | std::string _errorText; 104 | 105 | /** 106 | * The argument related to this exception. 107 | */ 108 | std::string _argId; 109 | 110 | /** 111 | * Describes the type of the exception. Used to distinguish 112 | * between different child exceptions. 113 | */ 114 | std::string _typeDescription; 115 | 116 | }; 117 | 118 | /** 119 | * Thrown from within the child Arg classes when it fails to properly 120 | * parse the argument it has been passed. 121 | */ 122 | class ArgParseException : public ArgException 123 | { 124 | public: 125 | /** 126 | * Constructor. 127 | * \param text - The text of the exception. 128 | * \param id - The text identifying the argument source 129 | * of the exception. 130 | */ 131 | ArgParseException( const std::string& text = "undefined exception", 132 | const std::string& id = "undefined" ) 133 | : ArgException( text, 134 | id, 135 | std::string( "Exception found while parsing " ) + 136 | std::string( "the value the Arg has been passed." )) 137 | { } 138 | }; 139 | 140 | /** 141 | * Thrown from CmdLine when the arguments on the command line are not 142 | * properly specified, e.g. too many arguments, required argument missing, etc. 143 | */ 144 | class CmdLineParseException : public ArgException 145 | { 146 | public: 147 | /** 148 | * Constructor. 149 | * \param text - The text of the exception. 150 | * \param id - The text identifying the argument source 151 | * of the exception. 152 | */ 153 | CmdLineParseException( const std::string& text = "undefined exception", 154 | const std::string& id = "undefined" ) 155 | : ArgException( text, 156 | id, 157 | std::string( "Exception found when the values ") + 158 | std::string( "on the command line do not meet ") + 159 | std::string( "the requirements of the defined ") + 160 | std::string( "Args." )) 161 | { } 162 | }; 163 | 164 | /** 165 | * Thrown from Arg and CmdLine when an Arg is improperly specified, e.g. 166 | * same flag as another Arg, same name, etc. 167 | */ 168 | class SpecificationException : public ArgException 169 | { 170 | public: 171 | /** 172 | * Constructor. 173 | * \param text - The text of the exception. 174 | * \param id - The text identifying the argument source 175 | * of the exception. 176 | */ 177 | SpecificationException( const std::string& text = "undefined exception", 178 | const std::string& id = "undefined" ) 179 | : ArgException( text, 180 | id, 181 | std::string("Exception found when an Arg object ")+ 182 | std::string("is improperly defined by the ") + 183 | std::string("developer." )) 184 | { } 185 | 186 | }; 187 | 188 | /** 189 | * Thrown when TCLAP thinks the program should exit. 190 | * 191 | * For example after parse error this exception will be thrown (and 192 | * normally caught). This allows any resource to be clened properly 193 | * before exit. 194 | * 195 | * If exception handling is disabled (CmdLine::setExceptionHandling), 196 | * this exception will propagate to the call site, allowing the 197 | * program to catch it and avoid program termination, or do it's own 198 | * cleanup. See for example, https://sourceforge.net/p/tclap/bugs/29. 199 | */ 200 | class ExitException { 201 | public: 202 | ExitException(int estat) : _estat(estat) {} 203 | 204 | int getExitStatus() const { return _estat; } 205 | 206 | private: 207 | int _estat; 208 | }; 209 | 210 | } // namespace TCLAP 211 | 212 | #endif 213 | 214 | -------------------------------------------------------------------------------- /include/tclap/ArgTraits.h: -------------------------------------------------------------------------------- 1 | // -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- 2 | 3 | /****************************************************************************** 4 | * 5 | * file: ArgTraits.h 6 | * 7 | * Copyright (c) 2007, Daniel Aarno, Michael E. Smoot . 8 | * Copyright (c) 2017 Google LLC 9 | * All rights reserved. 10 | * 11 | * See the file COPYING in the top directory of this distribution for 12 | * more information. 13 | * 14 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | * 22 | *****************************************************************************/ 23 | 24 | // This is an internal tclap file, you should probably not have to 25 | // include this directly 26 | 27 | #ifndef TCLAP_ARGTRAITS_H 28 | #define TCLAP_ARGTRAITS_H 29 | 30 | namespace TCLAP { 31 | 32 | // We use two empty structs to get compile type specialization 33 | // function to work 34 | 35 | /** 36 | * A value like argument value type is a value that can be set using 37 | * operator>>. This is the default value type. 38 | */ 39 | struct ValueLike { 40 | typedef ValueLike ValueCategory; 41 | virtual ~ValueLike() {} 42 | }; 43 | 44 | /** 45 | * A string like argument value type is a value that can be set using 46 | * operator=(string). Useful if the value type contains spaces which 47 | * will be broken up into individual tokens by operator>>. 48 | */ 49 | struct StringLike { 50 | virtual ~StringLike() {} 51 | }; 52 | 53 | /** 54 | * A class can inherit from this object to make it have string like 55 | * traits. This is a compile time thing and does not add any overhead 56 | * to the inherenting class. 57 | */ 58 | struct StringLikeTrait { 59 | typedef StringLike ValueCategory; 60 | virtual ~StringLikeTrait() {} 61 | }; 62 | 63 | /** 64 | * A class can inherit from this object to make it have value like 65 | * traits. This is a compile time thing and does not add any overhead 66 | * to the inherenting class. 67 | */ 68 | struct ValueLikeTrait { 69 | typedef ValueLike ValueCategory; 70 | virtual ~ValueLikeTrait() {} 71 | }; 72 | 73 | /** 74 | * Arg traits are used to get compile type specialization when parsing 75 | * argument values. Using an ArgTraits you can specify the way that 76 | * values gets assigned to any particular type during parsing. The two 77 | * supported types are StringLike and ValueLike. ValueLike is the 78 | * default and means that operator>> will be used to assign values to 79 | * the type. 80 | */ 81 | template 82 | class ArgTraits { 83 | // This is a bit silly, but what we want to do is: 84 | // 1) If there exists a specialization of ArgTraits for type X, 85 | // use it. 86 | // 87 | // 2) If no specialization exists but X has the typename 88 | // X::ValueCategory, use the specialization for X::ValueCategory. 89 | // 90 | // 3) If neither (1) nor (2) defines the trait, use the default 91 | // which is ValueLike. 92 | 93 | // This is the "how": 94 | // 95 | // test(0) (where 0 is the NULL ptr) will match 96 | // test(typename C::ValueCategory*) iff type T has the 97 | // corresponding typedef. If it does not test(...) will be 98 | // matched. This allows us to determine if T::ValueCategory 99 | // exists by checking the sizeof for the test function (return 100 | // value must have different sizeof). 101 | template static short test(typename C::ValueCategory*); 102 | template static long test(...); 103 | static const bool hasTrait = sizeof(test(0)) == sizeof(short); 104 | 105 | template 106 | struct DefaultArgTrait { 107 | typedef ValueLike ValueCategory; 108 | }; 109 | 110 | template 111 | struct DefaultArgTrait { 112 | typedef typename C::ValueCategory ValueCategory; 113 | }; 114 | 115 | public: 116 | typedef typename DefaultArgTrait::ValueCategory ValueCategory; 117 | }; 118 | 119 | } // namespace 120 | 121 | #endif 122 | 123 | -------------------------------------------------------------------------------- /include/tclap/CmdLineInterface.h: -------------------------------------------------------------------------------- 1 | // -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- 2 | 3 | 4 | /****************************************************************************** 5 | * 6 | * file: CmdLineInterface.h 7 | * 8 | * Copyright (c) 2003, Michael E. Smoot . 9 | * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. 10 | * Copyright (c) 2017, Google LLC 11 | * All rights reserved. 12 | * 13 | * See the file COPYING in the top directory of this distribution for 14 | * more information. 15 | * 16 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 17 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22 | * DEALINGS IN THE SOFTWARE. 23 | * 24 | *****************************************************************************/ 25 | 26 | #ifndef TCLAP_COMMANDLINE_INTERFACE_H 27 | #define TCLAP_COMMANDLINE_INTERFACE_H 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | 36 | namespace TCLAP { 37 | 38 | class Arg; 39 | class CmdLineOutput; 40 | class XorHandler; 41 | 42 | /** 43 | * The base class that manages the command line definition and passes 44 | * along the parsing to the appropriate Arg classes. 45 | */ 46 | class CmdLineInterface 47 | { 48 | public: 49 | 50 | /** 51 | * Destructor 52 | */ 53 | virtual ~CmdLineInterface() {} 54 | 55 | /** 56 | * Adds an argument to the list of arguments to be parsed. 57 | * \param a - Argument to be added. 58 | */ 59 | virtual void add( Arg& a )=0; 60 | 61 | /** 62 | * An alternative add. Functionally identical. 63 | * \param a - Argument to be added. 64 | */ 65 | virtual void add( Arg* a )=0; 66 | 67 | /** 68 | * Add two Args that will be xor'd. 69 | * If this method is used, add does 70 | * not need to be called. 71 | * \param a - Argument to be added and xor'd. 72 | * \param b - Argument to be added and xor'd. 73 | */ 74 | virtual void xorAdd( Arg& a, Arg& b )=0; 75 | 76 | /** 77 | * Add a list of Args that will be xor'd. If this method is used, 78 | * add does not need to be called. 79 | * \param xors - List of Args to be added and xor'd. 80 | */ 81 | virtual void xorAdd( const std::vector& xors )=0; 82 | 83 | /** 84 | * Parses the command line. 85 | * \param argc - Number of arguments. 86 | * \param argv - Array of arguments. 87 | */ 88 | virtual void parse(int argc, const char * const * argv)=0; 89 | 90 | /** 91 | * Parses the command line. 92 | * \param args - A vector of strings representing the args. 93 | * args[0] is still the program name. 94 | */ 95 | void parse(std::vector& args); 96 | 97 | /** 98 | * Returns the CmdLineOutput object. 99 | */ 100 | virtual CmdLineOutput* getOutput()=0; 101 | 102 | /** 103 | * \param co - CmdLineOutput object that we want to use instead. 104 | */ 105 | virtual void setOutput(CmdLineOutput* co)=0; 106 | 107 | /** 108 | * Returns the version string. 109 | */ 110 | virtual std::string& getVersion()=0; 111 | 112 | /** 113 | * Returns the program name string. 114 | */ 115 | virtual std::string& getProgramName()=0; 116 | 117 | /** 118 | * Returns the argList. 119 | */ 120 | virtual std::list& getArgList()=0; 121 | 122 | /** 123 | * Returns the XorHandler. 124 | */ 125 | virtual XorHandler& getXorHandler()=0; 126 | 127 | /** 128 | * Returns the delimiter string. 129 | */ 130 | virtual char getDelimiter()=0; 131 | 132 | /** 133 | * Returns the message string. 134 | */ 135 | virtual std::string& getMessage()=0; 136 | 137 | /** 138 | * Indicates whether or not the help and version switches were created 139 | * automatically. 140 | */ 141 | virtual bool hasHelpAndVersion()=0; 142 | 143 | /** 144 | * Resets the instance as if it had just been constructed so that the 145 | * instance can be reused. 146 | */ 147 | virtual void reset()=0; 148 | }; 149 | 150 | } //namespace 151 | 152 | 153 | #endif 154 | -------------------------------------------------------------------------------- /include/tclap/CmdLineOutput.h: -------------------------------------------------------------------------------- 1 | // -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- 2 | 3 | 4 | 5 | /****************************************************************************** 6 | * 7 | * file: CmdLineOutput.h 8 | * 9 | * Copyright (c) 2004, Michael E. Smoot 10 | * Copyright (c) 2017, Google LLC 11 | * All rights reserved. 12 | * 13 | * See the file COPYING in the top directory of this distribution for 14 | * more information. 15 | * 16 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 17 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22 | * DEALINGS IN THE SOFTWARE. 23 | * 24 | *****************************************************************************/ 25 | 26 | #ifndef TCLAP_CMDLINEOUTPUT_H 27 | #define TCLAP_CMDLINEOUTPUT_H 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | namespace TCLAP { 37 | 38 | class CmdLineInterface; 39 | class ArgException; 40 | 41 | /** 42 | * The interface that any output object must implement. 43 | */ 44 | class CmdLineOutput 45 | { 46 | 47 | public: 48 | 49 | /** 50 | * Virtual destructor. 51 | */ 52 | virtual ~CmdLineOutput() {} 53 | 54 | /** 55 | * Generates some sort of output for the USAGE. 56 | * \param c - The CmdLine object the output is generated for. 57 | */ 58 | virtual void usage(CmdLineInterface& c)=0; 59 | 60 | /** 61 | * Generates some sort of output for the version. 62 | * \param c - The CmdLine object the output is generated for. 63 | */ 64 | virtual void version(CmdLineInterface& c)=0; 65 | 66 | /** 67 | * Generates some sort of output for a failure. 68 | * \param c - The CmdLine object the output is generated for. 69 | * \param e - The ArgException that caused the failure. 70 | */ 71 | virtual void failure( CmdLineInterface& c, 72 | ArgException& e )=0; 73 | 74 | }; 75 | 76 | } //namespace TCLAP 77 | #endif 78 | -------------------------------------------------------------------------------- /include/tclap/Constraint.h: -------------------------------------------------------------------------------- 1 | // -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- 2 | 3 | 4 | /****************************************************************************** 5 | * 6 | * file: Constraint.h 7 | * 8 | * Copyright (c) 2005, Michael E. Smoot 9 | * Copyright (c) 2017, Google LLC 10 | * All rights reserved. 11 | * 12 | * See the file COPYING in the top directory of this distribution for 13 | * more information. 14 | * 15 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 16 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | * DEALINGS IN THE SOFTWARE. 22 | * 23 | *****************************************************************************/ 24 | 25 | #ifndef TCLAP_CONSTRAINT_H 26 | #define TCLAP_CONSTRAINT_H 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | namespace TCLAP { 37 | 38 | /** 39 | * The interface that defines the interaction between the Arg and Constraint. 40 | */ 41 | template 42 | class Constraint 43 | { 44 | 45 | public: 46 | /** 47 | * Returns a description of the Constraint. 48 | */ 49 | virtual std::string description() const =0; 50 | 51 | /** 52 | * Returns the short ID for the Constraint. 53 | */ 54 | virtual std::string shortID() const =0; 55 | 56 | /** 57 | * The method used to verify that the value parsed from the command 58 | * line meets the constraint. 59 | * \param value - The value that will be checked. 60 | */ 61 | virtual bool check(const T& value) const =0; 62 | 63 | /** 64 | * Destructor. 65 | * Silences warnings about Constraint being a base class with virtual 66 | * functions but without a virtual destructor. 67 | */ 68 | virtual ~Constraint() { ; } 69 | 70 | static std::string shortID(Constraint *constraint) { 71 | if (!constraint) 72 | throw std::logic_error("Cannot create a ValueArg with a NULL constraint"); 73 | return constraint->shortID(); 74 | } 75 | }; 76 | 77 | } //namespace TCLAP 78 | #endif 79 | -------------------------------------------------------------------------------- /include/tclap/DocBookOutput.h: -------------------------------------------------------------------------------- 1 | // -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- 2 | 3 | /****************************************************************************** 4 | * 5 | * file: DocBookOutput.h 6 | * 7 | * Copyright (c) 2004, Michael E. Smoot 8 | * Copyright (c) 2017, Google LLC 9 | * All rights reserved. 10 | * 11 | * See the file COPYING in the top directory of this distribution for 12 | * more information. 13 | * 14 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | * 22 | *****************************************************************************/ 23 | 24 | #ifndef TCLAP_DOCBOOKOUTPUT_H 25 | #define TCLAP_DOCBOOKOUTPUT_H 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #include 34 | #include 35 | #include 36 | #include 37 | 38 | namespace TCLAP { 39 | 40 | /** 41 | * A class that generates DocBook output for usage() method for the 42 | * given CmdLine and its Args. 43 | */ 44 | class DocBookOutput : public CmdLineOutput 45 | { 46 | 47 | public: 48 | 49 | /** 50 | * Prints the usage to stdout. Can be overridden to 51 | * produce alternative behavior. 52 | * \param c - The CmdLine object the output is generated for. 53 | */ 54 | virtual void usage(CmdLineInterface& c); 55 | 56 | /** 57 | * Prints the version to stdout. Can be overridden 58 | * to produce alternative behavior. 59 | * \param c - The CmdLine object the output is generated for. 60 | */ 61 | virtual void version(CmdLineInterface& c); 62 | 63 | /** 64 | * Prints (to stderr) an error message, short usage 65 | * Can be overridden to produce alternative behavior. 66 | * \param c - The CmdLine object the output is generated for. 67 | * \param e - The ArgException that caused the failure. 68 | */ 69 | virtual void failure(CmdLineInterface& c, 70 | ArgException& e ); 71 | 72 | DocBookOutput() : theDelimiter('=') {} 73 | protected: 74 | 75 | /** 76 | * Substitutes the char r for string x in string s. 77 | * \param s - The string to operate on. 78 | * \param r - The char to replace. 79 | * \param x - What to replace r with. 80 | */ 81 | void substituteSpecialChars( std::string& s, char r, std::string& x ); 82 | void removeChar( std::string& s, char r); 83 | void basename( std::string& s ); 84 | 85 | void printShortArg(Arg* it); 86 | void printLongArg(Arg* it); 87 | 88 | char theDelimiter; 89 | }; 90 | 91 | 92 | inline void DocBookOutput::version(CmdLineInterface& _cmd) 93 | { 94 | std::cout << _cmd.getVersion() << std::endl; 95 | } 96 | 97 | inline void DocBookOutput::usage(CmdLineInterface& _cmd ) 98 | { 99 | std::list argList = _cmd.getArgList(); 100 | std::string progName = _cmd.getProgramName(); 101 | std::string xversion = _cmd.getVersion(); 102 | theDelimiter = _cmd.getDelimiter(); 103 | XorHandler xorHandler = _cmd.getXorHandler(); 104 | const std::vector< std::vector > xorList = xorHandler.getXorList(); 105 | basename(progName); 106 | 107 | std::cout << "" << std::endl; 108 | std::cout << "" << std::endl << std::endl; 110 | 111 | std::cout << "" << std::endl; 112 | 113 | std::cout << "" << std::endl; 114 | std::cout << "" << progName << "" << std::endl; 115 | std::cout << "1" << std::endl; 116 | std::cout << "" << std::endl; 117 | 118 | std::cout << "" << std::endl; 119 | std::cout << "" << progName << "" << std::endl; 120 | std::cout << "" << _cmd.getMessage() << "" << std::endl; 121 | std::cout << "" << std::endl; 122 | 123 | std::cout << "" << std::endl; 124 | std::cout << "" << std::endl; 125 | 126 | std::cout << "" << progName << "" << std::endl; 127 | 128 | // xor 129 | for ( int i = 0; (unsigned int)i < xorList.size(); i++ ) 130 | { 131 | std::cout << "" << std::endl; 132 | for ( ArgVectorIterator it = xorList[i].begin(); 133 | it != xorList[i].end(); it++ ) 134 | printShortArg((*it)); 135 | 136 | std::cout << "" << std::endl; 137 | } 138 | 139 | // rest of args 140 | for (ArgListIterator it = argList.begin(); it != argList.end(); it++) 141 | if ( !xorHandler.contains( (*it) ) ) 142 | printShortArg((*it)); 143 | 144 | std::cout << "" << std::endl; 145 | std::cout << "" << std::endl; 146 | 147 | std::cout << "" << std::endl; 148 | std::cout << "Description" << std::endl; 149 | std::cout << "" << std::endl; 150 | std::cout << _cmd.getMessage() << std::endl; 151 | std::cout << "" << std::endl; 152 | std::cout << "" << std::endl; 153 | 154 | std::cout << "" << std::endl; 155 | std::cout << "Options" << std::endl; 156 | 157 | std::cout << "" << std::endl; 158 | 159 | for (ArgListIterator it = argList.begin(); it != argList.end(); it++) 160 | printLongArg((*it)); 161 | 162 | std::cout << "" << std::endl; 163 | std::cout << "" << std::endl; 164 | 165 | std::cout << "" << std::endl; 166 | std::cout << "Version" << std::endl; 167 | std::cout << "" << std::endl; 168 | std::cout << xversion << std::endl; 169 | std::cout << "" << std::endl; 170 | std::cout << "" << std::endl; 171 | 172 | std::cout << "" << std::endl; 173 | 174 | } 175 | 176 | inline void DocBookOutput::failure( CmdLineInterface& _cmd, 177 | ArgException& e ) 178 | { 179 | static_cast(_cmd); // unused 180 | std::cout << e.what() << std::endl; 181 | throw ExitException(1); 182 | } 183 | 184 | inline void DocBookOutput::substituteSpecialChars( std::string& s, 185 | char r, 186 | std::string& x ) 187 | { 188 | size_t p; 189 | while ( (p = s.find_first_of(r)) != std::string::npos ) 190 | { 191 | s.erase(p,1); 192 | s.insert(p,x); 193 | } 194 | } 195 | 196 | inline void DocBookOutput::removeChar( std::string& s, char r) 197 | { 198 | size_t p; 199 | while ( (p = s.find_first_of(r)) != std::string::npos ) 200 | { 201 | s.erase(p,1); 202 | } 203 | } 204 | 205 | inline void DocBookOutput::basename( std::string& s ) 206 | { 207 | size_t p = s.find_last_of('/'); 208 | if ( p != std::string::npos ) 209 | { 210 | s.erase(0, p + 1); 211 | } 212 | } 213 | 214 | inline void DocBookOutput::printShortArg(Arg* a) 215 | { 216 | std::string lt = "<"; 217 | std::string gt = ">"; 218 | 219 | std::string id = a->shortID(); 220 | substituteSpecialChars(id,'<',lt); 221 | substituteSpecialChars(id,'>',gt); 222 | removeChar(id,'['); 223 | removeChar(id,']'); 224 | 225 | std::string choice = "opt"; 226 | if ( a->isRequired() ) 227 | choice = "plain"; 228 | 229 | std::cout << "acceptsMultipleValues() ) 231 | std::cout << " rep='repeat'"; 232 | 233 | 234 | std::cout << '>'; 235 | if ( !a->getFlag().empty() ) 236 | std::cout << a->flagStartChar() << a->getFlag(); 237 | else 238 | std::cout << a->nameStartString() << a->getName(); 239 | if ( a->isValueRequired() ) 240 | { 241 | std::string arg = a->shortID(); 242 | removeChar(arg,'['); 243 | removeChar(arg,']'); 244 | removeChar(arg,'<'); 245 | removeChar(arg,'>'); 246 | removeChar(arg,'.'); 247 | arg.erase(0, arg.find_last_of(theDelimiter) + 1); 248 | std::cout << theDelimiter; 249 | std::cout << "" << arg << ""; 250 | } 251 | std::cout << "" << std::endl; 252 | 253 | } 254 | 255 | inline void DocBookOutput::printLongArg(Arg* a) 256 | { 257 | std::string lt = "<"; 258 | std::string gt = ">"; 259 | 260 | std::string desc = a->getDescription(); 261 | substituteSpecialChars(desc,'<',lt); 262 | substituteSpecialChars(desc,'>',gt); 263 | 264 | std::cout << "" << std::endl; 265 | 266 | if ( !a->getFlag().empty() ) 267 | { 268 | std::cout << "" << std::endl; 269 | std::cout << "" << std::endl; 272 | std::cout << "" << std::endl; 273 | } 274 | 275 | std::cout << "" << std::endl; 276 | std::cout << "" << std::endl; 291 | std::cout << "" << std::endl; 292 | 293 | std::cout << "" << std::endl; 294 | std::cout << "" << std::endl; 295 | std::cout << desc << std::endl; 296 | std::cout << "" << std::endl; 297 | std::cout << "" << std::endl; 298 | 299 | std::cout << "" << std::endl; 300 | } 301 | 302 | } //namespace TCLAP 303 | #endif 304 | -------------------------------------------------------------------------------- /include/tclap/HelpVisitor.h: -------------------------------------------------------------------------------- 1 | // -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- 2 | 3 | 4 | /****************************************************************************** 5 | * 6 | * file: HelpVisitor.h 7 | * 8 | * Copyright (c) 2003, Michael E. Smoot . 9 | * All rights reserved. 10 | * 11 | * See the file COPYING in the top directory of this distribution for 12 | * more information. 13 | * 14 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | * 22 | *****************************************************************************/ 23 | 24 | #ifndef TCLAP_HELP_VISITOR_H 25 | #define TCLAP_HELP_VISITOR_H 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | namespace TCLAP { 32 | 33 | /** 34 | * A Visitor object that calls the usage method of the given CmdLineOutput 35 | * object for the specified CmdLine object. 36 | */ 37 | class HelpVisitor: public Visitor 38 | { 39 | private: 40 | /** 41 | * Prevent accidental copying. 42 | */ 43 | HelpVisitor(const HelpVisitor& rhs); 44 | HelpVisitor& operator=(const HelpVisitor& rhs); 45 | 46 | protected: 47 | 48 | /** 49 | * The CmdLine the output will be generated for. 50 | */ 51 | CmdLineInterface* _cmd; 52 | 53 | /** 54 | * The output object. 55 | */ 56 | CmdLineOutput** _out; 57 | 58 | public: 59 | 60 | /** 61 | * Constructor. 62 | * \param cmd - The CmdLine the output will be generated for. 63 | * \param out - The type of output. 64 | */ 65 | HelpVisitor(CmdLineInterface* cmd, CmdLineOutput** out) 66 | : Visitor(), _cmd( cmd ), _out( out ) { } 67 | 68 | /** 69 | * Calls the usage method of the CmdLineOutput for the 70 | * specified CmdLine. 71 | */ 72 | void visit() { (*_out)->usage(*_cmd); throw ExitException(0); } 73 | 74 | }; 75 | 76 | } 77 | 78 | #endif 79 | -------------------------------------------------------------------------------- /include/tclap/IgnoreRestVisitor.h: -------------------------------------------------------------------------------- 1 | // -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- 2 | 3 | 4 | /****************************************************************************** 5 | * 6 | * file: IgnoreRestVisitor.h 7 | * 8 | * Copyright (c) 2003, Michael E. Smoot . 9 | * All rights reserved. 10 | * 11 | * See the file COPYING in the top directory of this distribution for 12 | * more information. 13 | * 14 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | * 22 | *****************************************************************************/ 23 | 24 | 25 | #ifndef TCLAP_IGNORE_REST_VISITOR_H 26 | #define TCLAP_IGNORE_REST_VISITOR_H 27 | 28 | #include 29 | #include 30 | 31 | namespace TCLAP { 32 | 33 | /** 34 | * A Visitor that tells the CmdLine to begin ignoring arguments after 35 | * this one is parsed. 36 | */ 37 | class IgnoreRestVisitor: public Visitor 38 | { 39 | public: 40 | 41 | /** 42 | * Constructor. 43 | */ 44 | IgnoreRestVisitor() : Visitor() {} 45 | 46 | /** 47 | * Sets Arg::_ignoreRest. 48 | */ 49 | void visit() { Arg::beginIgnoring(); } 50 | }; 51 | 52 | } 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /include/tclap/Makefile.am: -------------------------------------------------------------------------------- 1 | 2 | libtclapincludedir = $(includedir)/tclap 3 | 4 | libtclapinclude_HEADERS = \ 5 | Arg.h \ 6 | ArgException.h \ 7 | ArgTraits.h \ 8 | CmdLine.h \ 9 | CmdLineInterface.h \ 10 | CmdLineOutput.h \ 11 | Constraint.h \ 12 | DocBookOutput.h \ 13 | HelpVisitor.h \ 14 | IgnoreRestVisitor.h \ 15 | MultiArg.h \ 16 | MultiSwitchArg.h \ 17 | OptionalUnlabeledTracker.h \ 18 | StandardTraits.h \ 19 | StdOutput.h \ 20 | SwitchArg.h \ 21 | UnlabeledMultiArg.h \ 22 | UnlabeledValueArg.h \ 23 | ValueArg.h \ 24 | ValuesConstraint.h \ 25 | VersionVisitor.h \ 26 | Visitor.h \ 27 | XorHandler.h \ 28 | ZshCompletionOutput.h \ 29 | sstream.h 30 | -------------------------------------------------------------------------------- /include/tclap/MultiSwitchArg.h: -------------------------------------------------------------------------------- 1 | // -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- 2 | 3 | 4 | /****************************************************************************** 5 | * 6 | * file: MultiSwitchArg.h 7 | * 8 | * Copyright (c) 2003, Michael E. Smoot . 9 | * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. 10 | * Copyright (c) 2005, Michael E. Smoot, Daniel Aarno, Erik Zeek. 11 | * Copyright (c) 2017, Google LLC 12 | * All rights reserved. 13 | * 14 | * See the file COPYING in the top directory of this distribution for 15 | * more information. 16 | * 17 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | * DEALINGS IN THE SOFTWARE. 24 | * 25 | *****************************************************************************/ 26 | 27 | 28 | #ifndef TCLAP_MULTI_SWITCH_ARG_H 29 | #define TCLAP_MULTI_SWITCH_ARG_H 30 | 31 | #include 32 | #include 33 | 34 | #include 35 | 36 | namespace TCLAP { 37 | 38 | /** 39 | * A multiple switch argument. If the switch is set on the command line, then 40 | * the getValue method will return the number of times the switch appears. 41 | */ 42 | class MultiSwitchArg : public SwitchArg 43 | { 44 | protected: 45 | 46 | /** 47 | * The value of the switch. 48 | */ 49 | int _value; 50 | 51 | /** 52 | * Used to support the reset() method so that ValueArg can be 53 | * reset to their constructed value. 54 | */ 55 | int _default; 56 | 57 | public: 58 | 59 | /** 60 | * MultiSwitchArg constructor. 61 | * \param flag - The one character flag that identifies this 62 | * argument on the command line. 63 | * \param name - A one word name for the argument. Can be 64 | * used as a long flag on the command line. 65 | * \param desc - A description of what the argument is for or 66 | * does. 67 | * \param init - Optional. The initial/default value of this Arg. 68 | * Defaults to 0. 69 | * \param v - An optional visitor. You probably should not 70 | * use this unless you have a very good reason. 71 | */ 72 | MultiSwitchArg(const std::string& flag, 73 | const std::string& name, 74 | const std::string& desc, 75 | int init = 0, 76 | Visitor* v = NULL); 77 | 78 | 79 | /** 80 | * MultiSwitchArg constructor. 81 | * \param flag - The one character flag that identifies this 82 | * argument on the command line. 83 | * \param name - A one word name for the argument. Can be 84 | * used as a long flag on the command line. 85 | * \param desc - A description of what the argument is for or 86 | * does. 87 | * \param parser - A CmdLine parser object to add this Arg to 88 | * \param init - Optional. The initial/default value of this Arg. 89 | * Defaults to 0. 90 | * \param v - An optional visitor. You probably should not 91 | * use this unless you have a very good reason. 92 | */ 93 | MultiSwitchArg(const std::string& flag, 94 | const std::string& name, 95 | const std::string& desc, 96 | CmdLineInterface& parser, 97 | int init = 0, 98 | Visitor* v = NULL); 99 | 100 | 101 | /** 102 | * Handles the processing of the argument. 103 | * This re-implements the SwitchArg version of this method to set the 104 | * _value of the argument appropriately. 105 | * \param i - Pointer the the current argument in the list. 106 | * \param args - Mutable list of strings. Passed 107 | * in from main(). 108 | */ 109 | virtual bool processArg(int* i, std::vector& args); 110 | 111 | /** 112 | * Returns int, the number of times the switch has been set. 113 | */ 114 | int getValue() const { return _value; } 115 | 116 | /** 117 | * Returns the shortID for this Arg. 118 | */ 119 | std::string shortID(const std::string& val) const; 120 | 121 | /** 122 | * Returns the longID for this Arg. 123 | */ 124 | std::string longID(const std::string& val) const; 125 | 126 | void reset(); 127 | 128 | }; 129 | 130 | ////////////////////////////////////////////////////////////////////// 131 | //BEGIN MultiSwitchArg.cpp 132 | ////////////////////////////////////////////////////////////////////// 133 | inline MultiSwitchArg::MultiSwitchArg(const std::string& flag, 134 | const std::string& name, 135 | const std::string& desc, 136 | int init, 137 | Visitor* v ) 138 | : SwitchArg(flag, name, desc, false, v), 139 | _value( init ), 140 | _default( init ) 141 | { } 142 | 143 | inline MultiSwitchArg::MultiSwitchArg(const std::string& flag, 144 | const std::string& name, 145 | const std::string& desc, 146 | CmdLineInterface& parser, 147 | int init, 148 | Visitor* v ) 149 | : SwitchArg(flag, name, desc, false, v), 150 | _value( init ), 151 | _default( init ) 152 | { 153 | parser.add( this ); 154 | } 155 | 156 | inline bool MultiSwitchArg::processArg(int *i, std::vector& args) 157 | { 158 | if ( _ignoreable && Arg::ignoreRest() ) 159 | return false; 160 | 161 | if ( argMatches( args[*i] )) 162 | { 163 | // so the isSet() method will work 164 | _alreadySet = true; 165 | 166 | // Matched argument: increment value. 167 | ++_value; 168 | 169 | _checkWithVisitor(); 170 | 171 | return true; 172 | } 173 | else if ( combinedSwitchesMatch( args[*i] ) ) 174 | { 175 | // so the isSet() method will work 176 | _alreadySet = true; 177 | 178 | // Matched argument: increment value. 179 | ++_value; 180 | 181 | // Check for more in argument and increment value. 182 | while ( combinedSwitchesMatch( args[*i] ) ) 183 | ++_value; 184 | 185 | _checkWithVisitor(); 186 | 187 | return false; 188 | } 189 | else 190 | return false; 191 | } 192 | 193 | inline std::string 194 | MultiSwitchArg::shortID(const std::string& val) const 195 | { 196 | return Arg::shortID(val) + " ..."; 197 | } 198 | 199 | inline std::string 200 | MultiSwitchArg::longID(const std::string& val) const 201 | { 202 | return Arg::longID(val) + " (accepted multiple times)"; 203 | } 204 | 205 | inline void 206 | MultiSwitchArg::reset() 207 | { 208 | MultiSwitchArg::_value = MultiSwitchArg::_default; 209 | } 210 | 211 | ////////////////////////////////////////////////////////////////////// 212 | //END MultiSwitchArg.cpp 213 | ////////////////////////////////////////////////////////////////////// 214 | 215 | } //namespace TCLAP 216 | 217 | #endif 218 | -------------------------------------------------------------------------------- /include/tclap/OptionalUnlabeledTracker.h: -------------------------------------------------------------------------------- 1 | // -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- 2 | 3 | 4 | 5 | /****************************************************************************** 6 | * 7 | * file: OptionalUnlabeledTracker.h 8 | * 9 | * Copyright (c) 2005, Michael E. Smoot . 10 | * All rights reserved. 11 | * 12 | * See the file COPYING in the top directory of this distribution for 13 | * more information. 14 | * 15 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 16 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | * DEALINGS IN THE SOFTWARE. 22 | * 23 | *****************************************************************************/ 24 | 25 | 26 | #ifndef TCLAP_OPTIONAL_UNLABELED_TRACKER_H 27 | #define TCLAP_OPTIONAL_UNLABELED_TRACKER_H 28 | 29 | #include 30 | 31 | namespace TCLAP { 32 | 33 | class OptionalUnlabeledTracker 34 | { 35 | 36 | public: 37 | 38 | static void check( bool req, const std::string& argName ); 39 | 40 | static void gotOptional() { alreadyOptionalRef() = true; } 41 | 42 | static bool& alreadyOptional() { return alreadyOptionalRef(); } 43 | 44 | private: 45 | 46 | static bool& alreadyOptionalRef() { static bool ct = false; return ct; } 47 | }; 48 | 49 | 50 | inline void OptionalUnlabeledTracker::check( bool req, const std::string& argName ) 51 | { 52 | if ( OptionalUnlabeledTracker::alreadyOptional() ) 53 | throw( SpecificationException( 54 | "You can't specify ANY Unlabeled Arg following an optional Unlabeled Arg", 55 | argName ) ); 56 | 57 | if ( !req ) 58 | OptionalUnlabeledTracker::gotOptional(); 59 | } 60 | 61 | 62 | } // namespace TCLAP 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /include/tclap/StandardTraits.h: -------------------------------------------------------------------------------- 1 | // -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- 2 | 3 | /****************************************************************************** 4 | * 5 | * file: StandardTraits.h 6 | * 7 | * Copyright (c) 2007, Daniel Aarno, Michael E. Smoot . 8 | * Copyright (c) 2017, Google LLC 9 | * All rights reserved. 10 | * 11 | * See the file COPYING in the top directory of this distribution for 12 | * more information. 13 | * 14 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | * 22 | *****************************************************************************/ 23 | 24 | // This is an internal tclap file, you should probably not have to 25 | // include this directly 26 | 27 | #ifndef TCLAP_STANDARD_TRAITS_H 28 | #define TCLAP_STANDARD_TRAITS_H 29 | 30 | #ifdef HAVE_CONFIG_H 31 | #include // To check for long long 32 | #endif 33 | 34 | // If Microsoft has already typedef'd wchar_t as an unsigned 35 | // short, then compiles will break because it's as if we're 36 | // creating ArgTraits twice for unsigned short. Thus... 37 | #ifdef _MSC_VER 38 | #ifndef _NATIVE_WCHAR_T_DEFINED 39 | #define TCLAP_DONT_DECLARE_WCHAR_T_ARGTRAITS 40 | #endif 41 | #endif 42 | 43 | namespace TCLAP { 44 | 45 | // Integer types (signed, unsigned and bool) and floating point types all 46 | // have value-like semantics. 47 | 48 | // Strings have string like argument traits. 49 | template<> 50 | struct ArgTraits { 51 | typedef StringLike ValueCategory; 52 | }; 53 | 54 | template 55 | void SetString(T &dst, const std::string &src) 56 | { 57 | dst = src; 58 | } 59 | 60 | } // namespace 61 | 62 | #endif 63 | 64 | -------------------------------------------------------------------------------- /include/tclap/StdOutput.h: -------------------------------------------------------------------------------- 1 | // -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- 2 | 3 | /****************************************************************************** 4 | * 5 | * file: StdOutput.h 6 | * 7 | * Copyright (c) 2004, Michael E. Smoot 8 | * Copyright (c) 2017, Google LLC 9 | * All rights reserved. 10 | * 11 | * See the file COPYING in the top directory of this distribution for 12 | * more information. 13 | * 14 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | * 22 | *****************************************************************************/ 23 | 24 | #ifndef TCLAP_STDCMDLINEOUTPUT_H 25 | #define TCLAP_STDCMDLINEOUTPUT_H 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #include 34 | #include 35 | #include 36 | #include 37 | 38 | namespace TCLAP { 39 | 40 | /** 41 | * A class that isolates any output from the CmdLine object so that it 42 | * may be easily modified. 43 | */ 44 | class StdOutput : public CmdLineOutput 45 | { 46 | 47 | public: 48 | 49 | /** 50 | * Prints the usage to stdout. Can be overridden to 51 | * produce alternative behavior. 52 | * \param c - The CmdLine object the output is generated for. 53 | */ 54 | virtual void usage(CmdLineInterface& c); 55 | 56 | /** 57 | * Prints the version to stdout. Can be overridden 58 | * to produce alternative behavior. 59 | * \param c - The CmdLine object the output is generated for. 60 | */ 61 | virtual void version(CmdLineInterface& c); 62 | 63 | /** 64 | * Prints (to stderr) an error message, short usage 65 | * Can be overridden to produce alternative behavior. 66 | * \param c - The CmdLine object the output is generated for. 67 | * \param e - The ArgException that caused the failure. 68 | */ 69 | virtual void failure(CmdLineInterface& c, 70 | ArgException& e ); 71 | 72 | protected: 73 | 74 | /** 75 | * Writes a brief usage message with short args. 76 | * \param c - The CmdLine object the output is generated for. 77 | * \param os - The stream to write the message to. 78 | */ 79 | void _shortUsage( CmdLineInterface& c, std::ostream& os ) const; 80 | 81 | /** 82 | * Writes a longer usage message with long and short args, 83 | * provides descriptions and prints message. 84 | * \param c - The CmdLine object the output is generated for. 85 | * \param os - The stream to write the message to. 86 | */ 87 | void _longUsage( CmdLineInterface& c, std::ostream& os ) const; 88 | 89 | /** 90 | * This function inserts line breaks and indents long strings 91 | * according the params input. It will only break lines at spaces, 92 | * commas and pipes. 93 | * \param os - The stream to be printed to. 94 | * \param s - The string to be printed. 95 | * \param maxWidth - The maxWidth allowed for the output line. 96 | * \param indentSpaces - The number of spaces to indent the first line. 97 | * \param secondLineOffset - The number of spaces to indent the second 98 | * and all subsequent lines in addition to indentSpaces. 99 | */ 100 | void spacePrint( std::ostream& os, 101 | const std::string& s, 102 | int maxWidth, 103 | int indentSpaces, 104 | int secondLineOffset ) const; 105 | 106 | }; 107 | 108 | 109 | inline void StdOutput::version(CmdLineInterface& _cmd) 110 | { 111 | std::string progName = _cmd.getProgramName(); 112 | std::string xversion = _cmd.getVersion(); 113 | 114 | std::cout << std::endl << progName << " version: " 115 | << xversion << std::endl << std::endl; 116 | } 117 | 118 | inline void StdOutput::usage(CmdLineInterface& _cmd ) 119 | { 120 | std::cout << std::endl << "USAGE: " << std::endl << std::endl; 121 | 122 | _shortUsage( _cmd, std::cout ); 123 | 124 | std::cout << std::endl << std::endl << "Where: " << std::endl << std::endl; 125 | 126 | _longUsage( _cmd, std::cout ); 127 | 128 | std::cout << std::endl; 129 | 130 | } 131 | 132 | inline void StdOutput::failure( CmdLineInterface& _cmd, 133 | ArgException& e ) 134 | { 135 | std::string progName = _cmd.getProgramName(); 136 | 137 | std::cerr << "PARSE ERROR: " << e.argId() << std::endl 138 | << " " << e.error() << std::endl << std::endl; 139 | 140 | if ( _cmd.hasHelpAndVersion() ) 141 | { 142 | std::cerr << "Brief USAGE: " << std::endl; 143 | 144 | _shortUsage( _cmd, std::cerr ); 145 | 146 | std::cerr << std::endl << "For complete USAGE and HELP type: " 147 | << std::endl << " " << progName << " " 148 | << Arg::nameStartString() << "help" 149 | << std::endl << std::endl; 150 | } 151 | else 152 | usage(_cmd); 153 | 154 | throw ExitException(1); 155 | } 156 | 157 | inline void 158 | StdOutput::_shortUsage( CmdLineInterface& _cmd, 159 | std::ostream& os ) const 160 | { 161 | std::list argList = _cmd.getArgList(); 162 | std::string progName = _cmd.getProgramName(); 163 | XorHandler xorHandler = _cmd.getXorHandler(); 164 | std::vector< std::vector > xorList = xorHandler.getXorList(); 165 | 166 | std::string s = progName + " "; 167 | 168 | // first the xor 169 | for ( int i = 0; static_cast(i) < xorList.size(); i++ ) 170 | { 171 | s += " {"; 172 | for ( ArgVectorIterator it = xorList[i].begin(); 173 | it != xorList[i].end(); it++ ) 174 | s += (*it)->shortID() + "|"; 175 | 176 | s[s.length()-1] = '}'; 177 | } 178 | 179 | // then the rest 180 | for (ArgListIterator it = argList.begin(); it != argList.end(); it++) 181 | if ( !xorHandler.contains( (*it) ) ) 182 | s += " " + (*it)->shortID(); 183 | 184 | // if the program name is too long, then adjust the second line offset 185 | int secondLineOffset = static_cast(progName.length()) + 2; 186 | if ( secondLineOffset > 75/2 ) 187 | secondLineOffset = static_cast(75/2); 188 | 189 | spacePrint( os, s, 75, 3, secondLineOffset ); 190 | } 191 | 192 | inline void 193 | StdOutput::_longUsage( CmdLineInterface& _cmd, 194 | std::ostream& os ) const 195 | { 196 | std::list argList = _cmd.getArgList(); 197 | std::string message = _cmd.getMessage(); 198 | XorHandler xorHandler = _cmd.getXorHandler(); 199 | std::vector< std::vector > xorList = xorHandler.getXorList(); 200 | 201 | // first the xor 202 | for ( int i = 0; static_cast(i) < xorList.size(); i++ ) 203 | { 204 | for ( ArgVectorIterator it = xorList[i].begin(); 205 | it != xorList[i].end(); 206 | it++ ) 207 | { 208 | spacePrint( os, (*it)->longID(), 75, 3, 3 ); 209 | spacePrint( os, (*it)->getDescription(), 75, 5, 0 ); 210 | 211 | if ( it+1 != xorList[i].end() ) 212 | spacePrint(os, "-- OR --", 75, 9, 0); 213 | } 214 | os << std::endl << std::endl; 215 | } 216 | 217 | // then the rest 218 | for (ArgListIterator it = argList.begin(); it != argList.end(); it++) 219 | if ( !xorHandler.contains( (*it) ) ) 220 | { 221 | spacePrint( os, (*it)->longID(), 75, 3, 3 ); 222 | spacePrint( os, (*it)->getDescription(), 75, 5, 0 ); 223 | os << std::endl; 224 | } 225 | 226 | os << std::endl; 227 | 228 | spacePrint( os, message, 75, 3, 0 ); 229 | } 230 | 231 | inline void StdOutput::spacePrint( std::ostream& os, 232 | const std::string& s, 233 | int maxWidth, 234 | int indentSpaces, 235 | int secondLineOffset ) const 236 | { 237 | int len = static_cast(s.length()); 238 | 239 | if ( (len + indentSpaces > maxWidth) && maxWidth > 0 ) 240 | { 241 | int allowedLen = maxWidth - indentSpaces; 242 | int start = 0; 243 | while ( start < len ) 244 | { 245 | // find the substring length 246 | // int stringLen = std::min( len - start, allowedLen ); 247 | // doing it this way to support a VisualC++ 2005 bug 248 | using namespace std; 249 | int stringLen = min( len - start, allowedLen ); 250 | 251 | // trim the length so it doesn't end in middle of a word 252 | if ( stringLen == allowedLen ) 253 | while ( stringLen >= 0 && 254 | s[stringLen+start] != ' ' && 255 | s[stringLen+start] != ',' && 256 | s[stringLen+start] != '|' ) 257 | stringLen--; 258 | 259 | // ok, the word is longer than the line, so just split 260 | // wherever the line ends 261 | if ( stringLen <= 0 ) 262 | stringLen = allowedLen; 263 | 264 | // check for newlines 265 | for ( int i = 0; i < stringLen; i++ ) 266 | if ( s[start+i] == '\n' ) 267 | stringLen = i+1; 268 | 269 | // print the indent 270 | for ( int i = 0; i < indentSpaces; i++ ) 271 | os << " "; 272 | 273 | if ( start == 0 ) 274 | { 275 | // handle second line offsets 276 | indentSpaces += secondLineOffset; 277 | 278 | // adjust allowed len 279 | allowedLen -= secondLineOffset; 280 | } 281 | 282 | os << s.substr(start,stringLen) << std::endl; 283 | 284 | // so we don't start a line with a space 285 | while ( s[stringLen+start] == ' ' && start < len ) 286 | start++; 287 | 288 | start += stringLen; 289 | } 290 | } 291 | else 292 | { 293 | for ( int i = 0; i < indentSpaces; i++ ) 294 | os << " "; 295 | os << s << std::endl; 296 | } 297 | } 298 | 299 | } //namespace TCLAP 300 | #endif 301 | -------------------------------------------------------------------------------- /include/tclap/SwitchArg.h: -------------------------------------------------------------------------------- 1 | // -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- 2 | 3 | /****************************************************************************** 4 | * 5 | * file: SwitchArg.h 6 | * 7 | * Copyright (c) 2003, Michael E. Smoot . 8 | * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. 9 | * Copyright (c) 2017, Google LLC 10 | * All rights reserved. 11 | * 12 | * See the file COPYING in the top directory of this distribution for 13 | * more information. 14 | * 15 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 16 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | * DEALINGS IN THE SOFTWARE. 22 | * 23 | *****************************************************************************/ 24 | 25 | 26 | #ifndef TCLAP_SWITCH_ARG_H 27 | #define TCLAP_SWITCH_ARG_H 28 | 29 | #include 30 | #include 31 | 32 | #include 33 | 34 | namespace TCLAP { 35 | 36 | /** 37 | * A simple switch argument. If the switch is set on the command line, then 38 | * the getValue method will return the opposite of the default value for the 39 | * switch. 40 | */ 41 | class SwitchArg : public Arg 42 | { 43 | protected: 44 | 45 | /** 46 | * The value of the switch. 47 | */ 48 | bool _value; 49 | 50 | /** 51 | * Used to support the reset() method so that ValueArg can be 52 | * reset to their constructed value. 53 | */ 54 | bool _default; 55 | 56 | public: 57 | 58 | /** 59 | * SwitchArg constructor. 60 | * \param flag - The one character flag that identifies this 61 | * argument on the command line. 62 | * \param name - A one word name for the argument. Can be 63 | * used as a long flag on the command line. 64 | * \param desc - A description of what the argument is for or 65 | * does. 66 | * \param def - The default value for this Switch. 67 | * \param v - An optional visitor. You probably should not 68 | * use this unless you have a very good reason. 69 | */ 70 | SwitchArg(const std::string& flag, 71 | const std::string& name, 72 | const std::string& desc, 73 | bool def = false, 74 | Visitor* v = NULL); 75 | 76 | 77 | /** 78 | * SwitchArg constructor. 79 | * \param flag - The one character flag that identifies this 80 | * argument on the command line. 81 | * \param name - A one word name for the argument. Can be 82 | * used as a long flag on the command line. 83 | * \param desc - A description of what the argument is for or 84 | * does. 85 | * \param parser - A CmdLine parser object to add this Arg to 86 | * \param def - The default value for this Switch. 87 | * \param v - An optional visitor. You probably should not 88 | * use this unless you have a very good reason. 89 | */ 90 | SwitchArg(const std::string& flag, 91 | const std::string& name, 92 | const std::string& desc, 93 | CmdLineInterface& parser, 94 | bool def = false, 95 | Visitor* v = NULL); 96 | 97 | 98 | /** 99 | * Handles the processing of the argument. 100 | * This re-implements the Arg version of this method to set the 101 | * _value of the argument appropriately. 102 | * \param i - Pointer the the current argument in the list. 103 | * \param args - Mutable list of strings. Passed 104 | * in from main(). 105 | */ 106 | virtual bool processArg(int* i, std::vector& args); 107 | 108 | /** 109 | * Checks a string to see if any of the chars in the string 110 | * match the flag for this Switch. 111 | */ 112 | bool combinedSwitchesMatch(std::string& combined); 113 | 114 | /** 115 | * Returns bool, whether or not the switch has been set. 116 | */ 117 | bool getValue() const { return _value; } 118 | 119 | /** 120 | * A SwitchArg can be used as a boolean, indicating 121 | * whether or not the switch has been set. This is the 122 | * same as calling getValue() 123 | */ 124 | operator bool() const { return _value; } 125 | 126 | virtual void reset(); 127 | 128 | private: 129 | /** 130 | * Checks to see if we've found the last match in 131 | * a combined string. 132 | */ 133 | bool lastCombined(std::string& combined); 134 | 135 | /** 136 | * Does the common processing of processArg. 137 | */ 138 | void commonProcessing(); 139 | }; 140 | 141 | ////////////////////////////////////////////////////////////////////// 142 | //BEGIN SwitchArg.cpp 143 | ////////////////////////////////////////////////////////////////////// 144 | inline SwitchArg::SwitchArg(const std::string& flag, 145 | const std::string& name, 146 | const std::string& desc, 147 | bool default_val, 148 | Visitor* v ) 149 | : Arg(flag, name, desc, false, false, v), 150 | _value( default_val ), 151 | _default( default_val ) 152 | { } 153 | 154 | inline SwitchArg::SwitchArg(const std::string& flag, 155 | const std::string& name, 156 | const std::string& desc, 157 | CmdLineInterface& parser, 158 | bool default_val, 159 | Visitor* v ) 160 | : Arg(flag, name, desc, false, false, v), 161 | _value( default_val ), 162 | _default(default_val) 163 | { 164 | parser.add( this ); 165 | } 166 | 167 | inline bool SwitchArg::lastCombined(std::string& combinedSwitches ) 168 | { 169 | for ( unsigned int i = 1; i < combinedSwitches.length(); i++ ) 170 | if ( combinedSwitches[i] != Arg::blankChar() ) 171 | return false; 172 | 173 | return true; 174 | } 175 | 176 | inline bool SwitchArg::combinedSwitchesMatch(std::string& combinedSwitches ) 177 | { 178 | // make sure this is actually a combined switch 179 | if ( combinedSwitches.length() > 0 && 180 | combinedSwitches[0] != Arg::flagStartString()[0] ) 181 | return false; 182 | 183 | // make sure it isn't a long name 184 | if ( combinedSwitches.substr( 0, Arg::nameStartString().length() ) == 185 | Arg::nameStartString() ) 186 | return false; 187 | 188 | // make sure the delimiter isn't in the string 189 | if ( combinedSwitches.find_first_of(Arg::delimiter()) != std::string::npos) 190 | return false; 191 | 192 | // ok, we're not specifying a ValueArg, so we know that we have 193 | // a combined switch list. 194 | for ( unsigned int i = 1; i < combinedSwitches.length(); i++ ) 195 | if ( _flag.length() > 0 && 196 | combinedSwitches[i] == _flag[0] && 197 | _flag[0] != Arg::flagStartString()[0] ) 198 | { 199 | // update the combined switches so this one is no longer present 200 | // this is necessary so that no unlabeled args are matched 201 | // later in the processing. 202 | //combinedSwitches.erase(i,1); 203 | combinedSwitches[i] = Arg::blankChar(); 204 | return true; 205 | } 206 | 207 | // none of the switches passed in the list match. 208 | return false; 209 | } 210 | 211 | inline void SwitchArg::commonProcessing() 212 | { 213 | if ( _xorSet ) 214 | throw(CmdLineParseException( 215 | "Mutually exclusive argument already set!", toString())); 216 | 217 | if ( _alreadySet ) 218 | throw(CmdLineParseException("Argument already set!", toString())); 219 | 220 | _alreadySet = true; 221 | 222 | if ( _value == true ) 223 | _value = false; 224 | else 225 | _value = true; 226 | 227 | _checkWithVisitor(); 228 | } 229 | 230 | inline bool SwitchArg::processArg(int *i, std::vector& args) 231 | { 232 | if ( _ignoreable && Arg::ignoreRest() ) 233 | return false; 234 | 235 | // if the whole string matches the flag or name string 236 | if ( argMatches( args[*i] ) ) 237 | { 238 | commonProcessing(); 239 | 240 | return true; 241 | } 242 | // if a substring matches the flag as part of a combination 243 | else if ( combinedSwitchesMatch( args[*i] ) ) 244 | { 245 | // check again to ensure we don't misinterpret 246 | // this as a MultiSwitchArg 247 | if ( combinedSwitchesMatch( args[*i] ) ) 248 | throw(CmdLineParseException("Argument already set!", 249 | toString())); 250 | 251 | commonProcessing(); 252 | 253 | // We only want to return true if we've found the last combined 254 | // match in the string, otherwise we return true so that other 255 | // switches in the combination will have a chance to match. 256 | return lastCombined( args[*i] ); 257 | } 258 | else 259 | return false; 260 | } 261 | 262 | inline void SwitchArg::reset() 263 | { 264 | Arg::reset(); 265 | _value = _default; 266 | } 267 | ////////////////////////////////////////////////////////////////////// 268 | //End SwitchArg.cpp 269 | ////////////////////////////////////////////////////////////////////// 270 | 271 | } //namespace TCLAP 272 | 273 | #endif 274 | -------------------------------------------------------------------------------- /include/tclap/UnlabeledMultiArg.h: -------------------------------------------------------------------------------- 1 | // -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- 2 | 3 | 4 | /****************************************************************************** 5 | * 6 | * file: UnlabeledMultiArg.h 7 | * 8 | * Copyright (c) 2003, Michael E. Smoot. 9 | * Copyright (c) 2017, Google LLC 10 | * All rights reserved. 11 | * 12 | * See the file COPYING in the top directory of this distribution for 13 | * more information. 14 | * 15 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 16 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | * DEALINGS IN THE SOFTWARE. 22 | * 23 | *****************************************************************************/ 24 | 25 | 26 | #ifndef TCLAP_MULTIPLE_UNLABELED_ARGUMENT_H 27 | #define TCLAP_MULTIPLE_UNLABELED_ARGUMENT_H 28 | 29 | #include 30 | #include 31 | 32 | #include 33 | #include 34 | 35 | namespace TCLAP { 36 | 37 | /** 38 | * Just like a MultiArg, except that the arguments are unlabeled. Basically, 39 | * this Arg will slurp up everything that hasn't been matched to another 40 | * Arg. 41 | */ 42 | template 43 | class UnlabeledMultiArg : public MultiArg 44 | { 45 | 46 | // If compiler has two stage name lookup (as gcc >= 3.4 does) 47 | // this is required to prevent undef. symbols 48 | using MultiArg::_ignoreable; 49 | using MultiArg::_hasBlanks; 50 | using MultiArg::_extractValue; 51 | using MultiArg::_typeDesc; 52 | using MultiArg::_name; 53 | using MultiArg::_description; 54 | using MultiArg::_alreadySet; 55 | using MultiArg::toString; 56 | 57 | public: 58 | 59 | /** 60 | * Constructor. 61 | * \param name - The name of the Arg. Note that this is used for 62 | * identification, not as a long flag. 63 | * \param desc - A description of what the argument is for or 64 | * does. 65 | * \param req - Whether the argument is required on the command 66 | * line. 67 | * \param typeDesc - A short, human readable description of the 68 | * type that this object expects. This is used in the generation 69 | * of the USAGE statement. The goal is to be helpful to the end user 70 | * of the program. 71 | * \param ignoreable - Whether or not this argument can be ignored 72 | * using the "--" flag. 73 | * \param v - An optional visitor. You probably should not 74 | * use this unless you have a very good reason. 75 | */ 76 | UnlabeledMultiArg( const std::string& name, 77 | const std::string& desc, 78 | bool req, 79 | const std::string& typeDesc, 80 | bool ignoreable = false, 81 | Visitor* v = NULL ); 82 | /** 83 | * Constructor. 84 | * \param name - The name of the Arg. Note that this is used for 85 | * identification, not as a long flag. 86 | * \param desc - A description of what the argument is for or 87 | * does. 88 | * \param req - Whether the argument is required on the command 89 | * line. 90 | * \param typeDesc - A short, human readable description of the 91 | * type that this object expects. This is used in the generation 92 | * of the USAGE statement. The goal is to be helpful to the end user 93 | * of the program. 94 | * \param parser - A CmdLine parser object to add this Arg to 95 | * \param ignoreable - Whether or not this argument can be ignored 96 | * using the "--" flag. 97 | * \param v - An optional visitor. You probably should not 98 | * use this unless you have a very good reason. 99 | */ 100 | UnlabeledMultiArg( const std::string& name, 101 | const std::string& desc, 102 | bool req, 103 | const std::string& typeDesc, 104 | CmdLineInterface& parser, 105 | bool ignoreable = false, 106 | Visitor* v = NULL ); 107 | 108 | /** 109 | * Constructor. 110 | * \param name - The name of the Arg. Note that this is used for 111 | * identification, not as a long flag. 112 | * \param desc - A description of what the argument is for or 113 | * does. 114 | * \param req - Whether the argument is required on the command 115 | * line. 116 | * \param constraint - A pointer to a Constraint object used 117 | * to constrain this Arg. 118 | * \param ignoreable - Whether or not this argument can be ignored 119 | * using the "--" flag. 120 | * \param v - An optional visitor. You probably should not 121 | * use this unless you have a very good reason. 122 | */ 123 | UnlabeledMultiArg( const std::string& name, 124 | const std::string& desc, 125 | bool req, 126 | Constraint* constraint, 127 | bool ignoreable = false, 128 | Visitor* v = NULL ); 129 | 130 | /** 131 | * Constructor. 132 | * \param name - The name of the Arg. Note that this is used for 133 | * identification, not as a long flag. 134 | * \param desc - A description of what the argument is for or 135 | * does. 136 | * \param req - Whether the argument is required on the command 137 | * line. 138 | * \param constraint - A pointer to a Constraint object used 139 | * to constrain this Arg. 140 | * \param parser - A CmdLine parser object to add this Arg to 141 | * \param ignoreable - Whether or not this argument can be ignored 142 | * using the "--" flag. 143 | * \param v - An optional visitor. You probably should not 144 | * use this unless you have a very good reason. 145 | */ 146 | UnlabeledMultiArg( const std::string& name, 147 | const std::string& desc, 148 | bool req, 149 | Constraint* constraint, 150 | CmdLineInterface& parser, 151 | bool ignoreable = false, 152 | Visitor* v = NULL ); 153 | 154 | /** 155 | * Handles the processing of the argument. 156 | * This re-implements the Arg version of this method to set the 157 | * _value of the argument appropriately. It knows the difference 158 | * between labeled and unlabeled. 159 | * \param i - Pointer the the current argument in the list. 160 | * \param args - Mutable list of strings. Passed from main(). 161 | */ 162 | virtual bool processArg(int* i, std::vector& args); 163 | 164 | /** 165 | * Returns the a short id string. Used in the usage. 166 | * \param val - value to be used. 167 | */ 168 | virtual std::string shortID(const std::string& val="val") const; 169 | 170 | /** 171 | * Returns the a long id string. Used in the usage. 172 | * \param val - value to be used. 173 | */ 174 | virtual std::string longID(const std::string& val="val") const; 175 | 176 | /** 177 | * Operator ==. 178 | * \param a - The Arg to be compared to this. 179 | */ 180 | virtual bool operator==(const Arg& a) const; 181 | 182 | /** 183 | * Pushes this to back of list rather than front. 184 | * \param argList - The list this should be added to. 185 | */ 186 | virtual void addToList( std::list& argList ) const; 187 | }; 188 | 189 | template 190 | UnlabeledMultiArg::UnlabeledMultiArg(const std::string& name, 191 | const std::string& desc, 192 | bool req, 193 | const std::string& typeDesc, 194 | bool ignoreable, 195 | Visitor* v) 196 | : MultiArg("", name, desc, req, typeDesc, v) 197 | { 198 | _ignoreable = ignoreable; 199 | OptionalUnlabeledTracker::check(true, toString()); 200 | } 201 | 202 | template 203 | UnlabeledMultiArg::UnlabeledMultiArg(const std::string& name, 204 | const std::string& desc, 205 | bool req, 206 | const std::string& typeDesc, 207 | CmdLineInterface& parser, 208 | bool ignoreable, 209 | Visitor* v) 210 | : MultiArg("", name, desc, req, typeDesc, v) 211 | { 212 | _ignoreable = ignoreable; 213 | OptionalUnlabeledTracker::check(true, toString()); 214 | parser.add( this ); 215 | } 216 | 217 | 218 | template 219 | UnlabeledMultiArg::UnlabeledMultiArg(const std::string& name, 220 | const std::string& desc, 221 | bool req, 222 | Constraint* constraint, 223 | bool ignoreable, 224 | Visitor* v) 225 | : MultiArg("", name, desc, req, constraint, v) 226 | { 227 | _ignoreable = ignoreable; 228 | OptionalUnlabeledTracker::check(true, toString()); 229 | } 230 | 231 | template 232 | UnlabeledMultiArg::UnlabeledMultiArg(const std::string& name, 233 | const std::string& desc, 234 | bool req, 235 | Constraint* constraint, 236 | CmdLineInterface& parser, 237 | bool ignoreable, 238 | Visitor* v) 239 | : MultiArg("", name, desc, req, constraint, v) 240 | { 241 | _ignoreable = ignoreable; 242 | OptionalUnlabeledTracker::check(true, toString()); 243 | parser.add( this ); 244 | } 245 | 246 | 247 | template 248 | bool UnlabeledMultiArg::processArg(int *i, std::vector& args) 249 | { 250 | 251 | if ( _hasBlanks( args[*i] ) ) 252 | return false; 253 | 254 | // never ignore an unlabeled multi arg 255 | 256 | 257 | // always take the first value, regardless of the start string 258 | _extractValue( args[(*i)] ); 259 | 260 | /* 261 | // continue taking args until we hit the end or a start string 262 | while ( (unsigned int)(*i)+1 < args.size() && 263 | args[(*i)+1].find_first_of( Arg::flagStartString() ) != 0 && 264 | args[(*i)+1].find_first_of( Arg::nameStartString() ) != 0 ) 265 | _extractValue( args[++(*i)] ); 266 | */ 267 | 268 | _alreadySet = true; 269 | 270 | return true; 271 | } 272 | 273 | template 274 | std::string UnlabeledMultiArg::shortID(const std::string& val) const 275 | { 276 | static_cast(val); // Ignore input, don't warn 277 | return std::string("<") + _typeDesc + "> ..."; 278 | } 279 | 280 | template 281 | std::string UnlabeledMultiArg::longID(const std::string& val) const 282 | { 283 | static_cast(val); // Ignore input, don't warn 284 | return std::string("<") + _typeDesc + "> (accepted multiple times)"; 285 | } 286 | 287 | template 288 | bool UnlabeledMultiArg::operator==(const Arg& a) const 289 | { 290 | if ( _name == a.getName() || _description == a.getDescription() ) 291 | return true; 292 | else 293 | return false; 294 | } 295 | 296 | template 297 | void UnlabeledMultiArg::addToList( std::list& argList ) const 298 | { 299 | argList.push_back( const_cast(static_cast(this)) ); 300 | } 301 | 302 | } 303 | 304 | #endif 305 | -------------------------------------------------------------------------------- /include/tclap/UnlabeledValueArg.h: -------------------------------------------------------------------------------- 1 | // -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- 2 | 3 | 4 | /****************************************************************************** 5 | * 6 | * file: UnlabeledValueArg.h 7 | * 8 | * Copyright (c) 2003, Michael E. Smoot . 9 | * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. 10 | * Copyright (c) 2017, Google LLC 11 | * All rights reserved. 12 | * 13 | * See the file COPYING in the top directory of this distribution for 14 | * more information. 15 | * 16 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 17 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22 | * DEALINGS IN THE SOFTWARE. 23 | * 24 | *****************************************************************************/ 25 | 26 | 27 | #ifndef TCLAP_UNLABELED_VALUE_ARGUMENT_H 28 | #define TCLAP_UNLABELED_VALUE_ARGUMENT_H 29 | 30 | #include 31 | #include 32 | 33 | #include 34 | #include 35 | 36 | 37 | namespace TCLAP { 38 | 39 | /** 40 | * The basic unlabeled argument that parses a value. 41 | * This is a template class, which means the type T defines the type 42 | * that a given object will attempt to parse when an UnlabeledValueArg 43 | * is reached in the list of args that the CmdLine iterates over. 44 | */ 45 | template 46 | class UnlabeledValueArg : public ValueArg 47 | { 48 | 49 | // If compiler has two stage name lookup (as gcc >= 3.4 does) 50 | // this is required to prevent undef. symbols 51 | using ValueArg::_ignoreable; 52 | using ValueArg::_hasBlanks; 53 | using ValueArg::_extractValue; 54 | using ValueArg::_typeDesc; 55 | using ValueArg::_name; 56 | using ValueArg::_description; 57 | using ValueArg::_alreadySet; 58 | using ValueArg::toString; 59 | 60 | public: 61 | 62 | /** 63 | * UnlabeledValueArg constructor. 64 | * \param name - A one word name for the argument. Note that this is used for 65 | * identification, not as a long flag. 66 | * \param desc - A description of what the argument is for or 67 | * does. 68 | * \param req - Whether the argument is required on the command 69 | * line. 70 | * \param value - The default value assigned to this argument if it 71 | * is not present on the command line. 72 | * \param typeDesc - A short, human readable description of the 73 | * type that this object expects. This is used in the generation 74 | * of the USAGE statement. The goal is to be helpful to the end user 75 | * of the program. 76 | * \param ignoreable - Allows you to specify that this argument can be 77 | * ignored if the '--' flag is set. This defaults to false (cannot 78 | * be ignored) and should generally stay that way unless you have 79 | * some special need for certain arguments to be ignored. 80 | * \param v - Optional Visitor. You should leave this blank unless 81 | * you have a very good reason. 82 | */ 83 | UnlabeledValueArg( const std::string& name, 84 | const std::string& desc, 85 | bool req, 86 | T value, 87 | const std::string& typeDesc, 88 | bool ignoreable = false, 89 | Visitor* v = NULL); 90 | 91 | /** 92 | * UnlabeledValueArg constructor. 93 | * \param name - A one word name for the argument. Note that this is used for 94 | * identification, not as a long flag. 95 | * \param desc - A description of what the argument is for or 96 | * does. 97 | * \param req - Whether the argument is required on the command 98 | * line. 99 | * \param value - The default value assigned to this argument if it 100 | * is not present on the command line. 101 | * \param typeDesc - A short, human readable description of the 102 | * type that this object expects. This is used in the generation 103 | * of the USAGE statement. The goal is to be helpful to the end user 104 | * of the program. 105 | * \param parser - A CmdLine parser object to add this Arg to 106 | * \param ignoreable - Allows you to specify that this argument can be 107 | * ignored if the '--' flag is set. This defaults to false (cannot 108 | * be ignored) and should generally stay that way unless you have 109 | * some special need for certain arguments to be ignored. 110 | * \param v - Optional Visitor. You should leave this blank unless 111 | * you have a very good reason. 112 | */ 113 | UnlabeledValueArg( const std::string& name, 114 | const std::string& desc, 115 | bool req, 116 | T value, 117 | const std::string& typeDesc, 118 | CmdLineInterface& parser, 119 | bool ignoreable = false, 120 | Visitor* v = NULL ); 121 | 122 | /** 123 | * UnlabeledValueArg constructor. 124 | * \param name - A one word name for the argument. Note that this is used for 125 | * identification, not as a long flag. 126 | * \param desc - A description of what the argument is for or 127 | * does. 128 | * \param req - Whether the argument is required on the command 129 | * line. 130 | * \param value - The default value assigned to this argument if it 131 | * is not present on the command line. 132 | * \param constraint - A pointer to a Constraint object used 133 | * to constrain this Arg. 134 | * \param ignoreable - Allows you to specify that this argument can be 135 | * ignored if the '--' flag is set. This defaults to false (cannot 136 | * be ignored) and should generally stay that way unless you have 137 | * some special need for certain arguments to be ignored. 138 | * \param v - Optional Visitor. You should leave this blank unless 139 | * you have a very good reason. 140 | */ 141 | UnlabeledValueArg( const std::string& name, 142 | const std::string& desc, 143 | bool req, 144 | T value, 145 | Constraint* constraint, 146 | bool ignoreable = false, 147 | Visitor* v = NULL ); 148 | 149 | 150 | /** 151 | * UnlabeledValueArg constructor. 152 | * \param name - A one word name for the argument. Note that this is used for 153 | * identification, not as a long flag. 154 | * \param desc - A description of what the argument is for or 155 | * does. 156 | * \param req - Whether the argument is required on the command 157 | * line. 158 | * \param value - The default value assigned to this argument if it 159 | * is not present on the command line. 160 | * \param constraint - A pointer to a Constraint object used 161 | * to constrain this Arg. 162 | * \param parser - A CmdLine parser object to add this Arg to 163 | * \param ignoreable - Allows you to specify that this argument can be 164 | * ignored if the '--' flag is set. This defaults to false (cannot 165 | * be ignored) and should generally stay that way unless you have 166 | * some special need for certain arguments to be ignored. 167 | * \param v - Optional Visitor. You should leave this blank unless 168 | * you have a very good reason. 169 | */ 170 | UnlabeledValueArg( const std::string& name, 171 | const std::string& desc, 172 | bool req, 173 | T value, 174 | Constraint* constraint, 175 | CmdLineInterface& parser, 176 | bool ignoreable = false, 177 | Visitor* v = NULL); 178 | 179 | /** 180 | * Handles the processing of the argument. 181 | * This re-implements the Arg version of this method to set the 182 | * _value of the argument appropriately. Handling specific to 183 | * unlabeled arguments. 184 | * \param i - Pointer the the current argument in the list. 185 | * \param args - Mutable list of strings. 186 | */ 187 | virtual bool processArg(int* i, std::vector& args); 188 | 189 | /** 190 | * Overrides shortID for specific behavior. 191 | */ 192 | virtual std::string shortID(const std::string& val="val") const; 193 | 194 | /** 195 | * Overrides longID for specific behavior. 196 | */ 197 | virtual std::string longID(const std::string& val="val") const; 198 | 199 | /** 200 | * Overrides operator== for specific behavior. 201 | */ 202 | virtual bool operator==(const Arg& a ) const; 203 | 204 | /** 205 | * Instead of pushing to the front of list, push to the back. 206 | * \param argList - The list to add this to. 207 | */ 208 | virtual void addToList( std::list& argList ) const; 209 | 210 | }; 211 | 212 | /** 213 | * Constructor implementation. 214 | */ 215 | template 216 | UnlabeledValueArg::UnlabeledValueArg(const std::string& name, 217 | const std::string& desc, 218 | bool req, 219 | T val, 220 | const std::string& typeDesc, 221 | bool ignoreable, 222 | Visitor* v) 223 | : ValueArg("", name, desc, req, val, typeDesc, v) 224 | { 225 | _ignoreable = ignoreable; 226 | 227 | OptionalUnlabeledTracker::check(req, toString()); 228 | 229 | } 230 | 231 | template 232 | UnlabeledValueArg::UnlabeledValueArg(const std::string& name, 233 | const std::string& desc, 234 | bool req, 235 | T val, 236 | const std::string& typeDesc, 237 | CmdLineInterface& parser, 238 | bool ignoreable, 239 | Visitor* v) 240 | : ValueArg("", name, desc, req, val, typeDesc, v) 241 | { 242 | _ignoreable = ignoreable; 243 | OptionalUnlabeledTracker::check(req, toString()); 244 | parser.add( this ); 245 | } 246 | 247 | /** 248 | * Constructor implementation. 249 | */ 250 | template 251 | UnlabeledValueArg::UnlabeledValueArg(const std::string& name, 252 | const std::string& desc, 253 | bool req, 254 | T val, 255 | Constraint* constraint, 256 | bool ignoreable, 257 | Visitor* v) 258 | : ValueArg("", name, desc, req, val, constraint, v) 259 | { 260 | _ignoreable = ignoreable; 261 | OptionalUnlabeledTracker::check(req, toString()); 262 | } 263 | 264 | template 265 | UnlabeledValueArg::UnlabeledValueArg(const std::string& name, 266 | const std::string& desc, 267 | bool req, 268 | T val, 269 | Constraint* constraint, 270 | CmdLineInterface& parser, 271 | bool ignoreable, 272 | Visitor* v) 273 | : ValueArg("", name, desc, req, val, constraint, v) 274 | { 275 | _ignoreable = ignoreable; 276 | OptionalUnlabeledTracker::check(req, toString()); 277 | parser.add( this ); 278 | } 279 | 280 | /** 281 | * Implementation of processArg(). 282 | */ 283 | template 284 | bool UnlabeledValueArg::processArg(int *i, std::vector& args) 285 | { 286 | 287 | if ( _alreadySet ) 288 | return false; 289 | 290 | if ( _hasBlanks( args[*i] ) ) 291 | return false; 292 | 293 | // never ignore an unlabeled arg 294 | 295 | _extractValue( args[*i] ); 296 | _alreadySet = true; 297 | return true; 298 | } 299 | 300 | /** 301 | * Overriding shortID for specific output. 302 | */ 303 | template 304 | std::string UnlabeledValueArg::shortID(const std::string& val) const 305 | { 306 | static_cast(val); // Ignore input, don't warn 307 | return std::string("<") + _typeDesc + ">"; 308 | } 309 | 310 | /** 311 | * Overriding longID for specific output. 312 | */ 313 | template 314 | std::string UnlabeledValueArg::longID(const std::string& val) const 315 | { 316 | static_cast(val); // Ignore input, don't warn 317 | 318 | // Ideally we would like to be able to use RTTI to return the name 319 | // of the type required for this argument. However, g++ at least, 320 | // doesn't appear to return terribly useful "names" of the types. 321 | return std::string("<") + _typeDesc + ">"; 322 | } 323 | 324 | /** 325 | * Overriding operator== for specific behavior. 326 | */ 327 | template 328 | bool UnlabeledValueArg::operator==(const Arg& a ) const 329 | { 330 | if ( _name == a.getName() || _description == a.getDescription() ) 331 | return true; 332 | else 333 | return false; 334 | } 335 | 336 | template 337 | void UnlabeledValueArg::addToList( std::list& argList ) const 338 | { 339 | argList.push_back( const_cast(static_cast(this)) ); 340 | } 341 | 342 | } 343 | #endif 344 | -------------------------------------------------------------------------------- /include/tclap/ValuesConstraint.h: -------------------------------------------------------------------------------- 1 | // -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- 2 | 3 | 4 | 5 | /****************************************************************************** 6 | * 7 | * file: ValuesConstraint.h 8 | * 9 | * Copyright (c) 2005, Michael E. Smoot 10 | * Copyright (c) 2017, Google LLC 11 | * All rights reserved. 12 | * 13 | * See the file COPYING in the top directory of this distribution for 14 | * more information. 15 | * 16 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 17 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22 | * DEALINGS IN THE SOFTWARE. 23 | * 24 | *****************************************************************************/ 25 | 26 | #ifndef TCLAP_VALUESCONSTRAINT_H 27 | #define TCLAP_VALUESCONSTRAINT_H 28 | 29 | #ifdef HAVE_CONFIG_H 30 | #include 31 | #endif 32 | 33 | #include 34 | #include 35 | #include 36 | #include 37 | 38 | namespace TCLAP { 39 | 40 | /** 41 | * A Constraint that constrains the Arg to only those values specified 42 | * in the constraint. 43 | */ 44 | template 45 | class ValuesConstraint : public Constraint 46 | { 47 | 48 | public: 49 | 50 | /** 51 | * Constructor. 52 | * \param allowed - vector of allowed values. 53 | */ 54 | ValuesConstraint(std::vectorconst& allowed); 55 | 56 | /** 57 | * Virtual destructor. 58 | */ 59 | virtual ~ValuesConstraint() {} 60 | 61 | /** 62 | * Returns a description of the Constraint. 63 | */ 64 | virtual std::string description() const; 65 | 66 | /** 67 | * Returns the short ID for the Constraint. 68 | */ 69 | virtual std::string shortID() const; 70 | 71 | /** 72 | * The method used to verify that the value parsed from the command 73 | * line meets the constraint. 74 | * \param value - The value that will be checked. 75 | */ 76 | virtual bool check(const T& value) const; 77 | 78 | protected: 79 | 80 | /** 81 | * The list of valid values. 82 | */ 83 | std::vector _allowed; 84 | 85 | /** 86 | * The string used to describe the allowed values of this constraint. 87 | */ 88 | std::string _typeDesc; 89 | 90 | }; 91 | 92 | template 93 | ValuesConstraint::ValuesConstraint(std::vector const& allowed) 94 | : _allowed(allowed), 95 | _typeDesc("") 96 | { 97 | for ( unsigned int i = 0; i < _allowed.size(); i++ ) 98 | { 99 | std::ostringstream os; 100 | os << _allowed[i]; 101 | 102 | std::string temp( os.str() ); 103 | 104 | if ( i > 0 ) 105 | _typeDesc += "|"; 106 | _typeDesc += temp; 107 | } 108 | } 109 | 110 | template 111 | bool ValuesConstraint::check( const T& val ) const 112 | { 113 | if ( std::find(_allowed.begin(),_allowed.end(),val) == _allowed.end() ) 114 | return false; 115 | else 116 | return true; 117 | } 118 | 119 | template 120 | std::string ValuesConstraint::shortID() const 121 | { 122 | return _typeDesc; 123 | } 124 | 125 | template 126 | std::string ValuesConstraint::description() const 127 | { 128 | return _typeDesc; 129 | } 130 | 131 | 132 | } //namespace TCLAP 133 | #endif 134 | 135 | -------------------------------------------------------------------------------- /include/tclap/VersionVisitor.h: -------------------------------------------------------------------------------- 1 | // -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- 2 | 3 | /****************************************************************************** 4 | * 5 | * file: VersionVisitor.h 6 | * 7 | * Copyright (c) 2003, Michael E. Smoot . 8 | * All rights reserved. 9 | * 10 | * See the file COPYING in the top directory of this distribution for 11 | * more information. 12 | * 13 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 14 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | * DEALINGS IN THE SOFTWARE. 20 | * 21 | *****************************************************************************/ 22 | 23 | 24 | #ifndef TCLAP_VERSION_VISITOR_H 25 | #define TCLAP_VERSION_VISITOR_H 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | namespace TCLAP { 32 | 33 | /** 34 | * A Visitor that will call the version method of the given CmdLineOutput 35 | * for the specified CmdLine object and then exit. 36 | */ 37 | class VersionVisitor: public Visitor 38 | { 39 | private: 40 | /** 41 | * Prevent accidental copying 42 | */ 43 | VersionVisitor(const VersionVisitor& rhs); 44 | VersionVisitor& operator=(const VersionVisitor& rhs); 45 | 46 | protected: 47 | 48 | /** 49 | * The CmdLine of interest. 50 | */ 51 | CmdLineInterface* _cmd; 52 | 53 | /** 54 | * The output object. 55 | */ 56 | CmdLineOutput** _out; 57 | 58 | public: 59 | 60 | /** 61 | * Constructor. 62 | * \param cmd - The CmdLine the output is generated for. 63 | * \param out - The type of output. 64 | */ 65 | VersionVisitor( CmdLineInterface* cmd, CmdLineOutput** out ) 66 | : Visitor(), _cmd( cmd ), _out( out ) { } 67 | 68 | /** 69 | * Calls the version method of the output object using the 70 | * specified CmdLine. 71 | */ 72 | void visit() { 73 | (*_out)->version(*_cmd); 74 | throw ExitException(0); 75 | } 76 | 77 | }; 78 | 79 | } 80 | 81 | #endif 82 | -------------------------------------------------------------------------------- /include/tclap/Visitor.h: -------------------------------------------------------------------------------- 1 | // -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- 2 | 3 | 4 | /****************************************************************************** 5 | * 6 | * file: Visitor.h 7 | * 8 | * Copyright (c) 2003, Michael E. Smoot . 9 | * Copyright (c) 2017, Google LLC 10 | * All rights reserved. 11 | * 12 | * See the file COPYING in the top directory of this distribution for 13 | * more information. 14 | * 15 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 16 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | * DEALINGS IN THE SOFTWARE. 22 | * 23 | *****************************************************************************/ 24 | 25 | 26 | #ifndef TCLAP_VISITOR_H 27 | #define TCLAP_VISITOR_H 28 | 29 | namespace TCLAP { 30 | 31 | /** 32 | * A base class that defines the interface for visitors. 33 | */ 34 | class Visitor 35 | { 36 | public: 37 | 38 | /** 39 | * Constructor. Does nothing. 40 | */ 41 | Visitor() { } 42 | 43 | /** 44 | * Destructor. Does nothing. 45 | */ 46 | virtual ~Visitor() { } 47 | 48 | /** 49 | * This method (to implemented by children) will be 50 | * called when the visitor is visited. 51 | */ 52 | virtual void visit() = 0; 53 | }; 54 | 55 | } 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /include/tclap/XorHandler.h: -------------------------------------------------------------------------------- 1 | // -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- 2 | 3 | 4 | /****************************************************************************** 5 | * 6 | * file: XorHandler.h 7 | * 8 | * Copyright (c) 2003, Michael E. Smoot . 9 | * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno. 10 | * All rights reserved. 11 | * 12 | * See the file COPYING in the top directory of this distribution for 13 | * more information. 14 | * 15 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 16 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | * DEALINGS IN THE SOFTWARE. 22 | * 23 | *****************************************************************************/ 24 | 25 | #ifndef TCLAP_XORHANDLER_H 26 | #define TCLAP_XORHANDLER_H 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | namespace TCLAP { 35 | 36 | /** 37 | * This class handles lists of Arg's that are to be XOR'd on the command 38 | * line. This is used by CmdLine and you shouldn't ever use it. 39 | */ 40 | class XorHandler 41 | { 42 | protected: 43 | 44 | /** 45 | * The list of of lists of Arg's to be or'd together. 46 | */ 47 | std::vector< std::vector > _orList; 48 | 49 | public: 50 | 51 | /** 52 | * Constructor. Does nothing. 53 | */ 54 | XorHandler( ) : _orList(std::vector< std::vector >()) {} 55 | 56 | /** 57 | * Add a list of Arg*'s that will be xor'd together. 58 | * \param ors - list of Arg* that will be xor'd. 59 | */ 60 | void add( const std::vector& ors ); 61 | 62 | /** 63 | * Checks whether the specified Arg is in one of the xor lists and 64 | * if it does match one, returns the size of the xor list that the 65 | * Arg matched. If the Arg matches, then it also sets the rest of 66 | * the Arg's in the list. You shouldn't use this. 67 | * \param a - The Arg to be checked. 68 | */ 69 | int check( const Arg* a ); 70 | 71 | /** 72 | * Returns the XOR specific short usage. 73 | */ 74 | std::string shortUsage(); 75 | 76 | /** 77 | * Prints the XOR specific long usage. 78 | * \param os - Stream to print to. 79 | */ 80 | void printLongUsage(std::ostream& os); 81 | 82 | /** 83 | * Simply checks whether the Arg is contained in one of the arg 84 | * lists. 85 | * \param a - The Arg to be checked. 86 | */ 87 | bool contains( const Arg* a ); 88 | 89 | const std::vector< std::vector >& getXorList() const; 90 | 91 | }; 92 | 93 | 94 | ////////////////////////////////////////////////////////////////////// 95 | //BEGIN XOR.cpp 96 | ////////////////////////////////////////////////////////////////////// 97 | inline void XorHandler::add( const std::vector& ors ) 98 | { 99 | _orList.push_back( ors ); 100 | } 101 | 102 | inline int XorHandler::check( const Arg* a ) 103 | { 104 | // iterate over each XOR list 105 | for ( int i = 0; static_cast(i) < _orList.size(); i++ ) 106 | { 107 | // if the XOR list contains the arg.. 108 | ArgVectorIterator ait = std::find( _orList[i].begin(), 109 | _orList[i].end(), a ); 110 | if ( ait != _orList[i].end() ) 111 | { 112 | // first check to see if a mutually exclusive switch 113 | // has not already been set 114 | for ( ArgVectorIterator it = _orList[i].begin(); 115 | it != _orList[i].end(); 116 | it++ ) 117 | if ( a != (*it) && (*it)->isSet() ) 118 | throw(CmdLineParseException( 119 | "Mutually exclusive argument already set!", 120 | (*it)->toString())); 121 | 122 | // go through and set each arg that is not a 123 | for ( ArgVectorIterator it = _orList[i].begin(); 124 | it != _orList[i].end(); 125 | it++ ) 126 | if ( a != (*it) ) 127 | (*it)->xorSet(); 128 | 129 | // return the number of required args that have now been set 130 | if ( (*ait)->allowMore() ) 131 | return 0; 132 | else 133 | return static_cast(_orList[i].size()); 134 | } 135 | } 136 | 137 | if ( a->isRequired() ) 138 | return 1; 139 | else 140 | return 0; 141 | } 142 | 143 | inline bool XorHandler::contains( const Arg* a ) 144 | { 145 | for ( int i = 0; static_cast(i) < _orList.size(); i++ ) 146 | for ( ArgVectorIterator it = _orList[i].begin(); 147 | it != _orList[i].end(); 148 | it++ ) 149 | if ( a == (*it) ) 150 | return true; 151 | 152 | return false; 153 | } 154 | 155 | inline const std::vector< std::vector >& XorHandler::getXorList() const 156 | { 157 | return _orList; 158 | } 159 | 160 | 161 | 162 | ////////////////////////////////////////////////////////////////////// 163 | //END XOR.cpp 164 | ////////////////////////////////////////////////////////////////////// 165 | 166 | } //namespace TCLAP 167 | 168 | #endif 169 | -------------------------------------------------------------------------------- /include/tclap/ZshCompletionOutput.h: -------------------------------------------------------------------------------- 1 | // -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- 2 | 3 | /****************************************************************************** 4 | * 5 | * file: ZshCompletionOutput.h 6 | * 7 | * Copyright (c) 2006, Oliver Kiddle 8 | * Copyright (c) 2017 Google Inc. 9 | * All rights reserved. 10 | * 11 | * See the file COPYING in the top directory of this distribution for 12 | * more information. 13 | * 14 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | * 22 | *****************************************************************************/ 23 | 24 | #ifndef TCLAP_ZSHCOMPLETIONOUTPUT_H 25 | #define TCLAP_ZSHCOMPLETIONOUTPUT_H 26 | 27 | #ifdef HAVE_CONFIG_H 28 | #include 29 | #endif 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | 43 | namespace TCLAP { 44 | 45 | /** 46 | * A class that generates a Zsh completion function as output from the usage() 47 | * method for the given CmdLine and its Args. 48 | */ 49 | class ZshCompletionOutput : public CmdLineOutput 50 | { 51 | 52 | public: 53 | 54 | ZshCompletionOutput(); 55 | 56 | /** 57 | * Prints the usage to stdout. Can be overridden to 58 | * produce alternative behavior. 59 | * \param c - The CmdLine object the output is generated for. 60 | */ 61 | virtual void usage(CmdLineInterface& c); 62 | 63 | /** 64 | * Prints the version to stdout. Can be overridden 65 | * to produce alternative behavior. 66 | * \param c - The CmdLine object the output is generated for. 67 | */ 68 | virtual void version(CmdLineInterface& c); 69 | 70 | /** 71 | * Prints (to stderr) an error message, short usage 72 | * Can be overridden to produce alternative behavior. 73 | * \param c - The CmdLine object the output is generated for. 74 | * \param e - The ArgException that caused the failure. 75 | */ 76 | virtual void failure(CmdLineInterface& c, 77 | ArgException& e ); 78 | 79 | protected: 80 | 81 | void basename( std::string& s ); 82 | void quoteSpecialChars( std::string& s ); 83 | 84 | std::string getMutexList( CmdLineInterface& _cmd, Arg* a ); 85 | void printOption( Arg* it, std::string mutex ); 86 | void printArg( Arg* it ); 87 | 88 | std::map common; 89 | char theDelimiter; 90 | }; 91 | 92 | ZshCompletionOutput::ZshCompletionOutput() 93 | : common(std::map()), 94 | theDelimiter('=') 95 | { 96 | common["host"] = "_hosts"; 97 | common["hostname"] = "_hosts"; 98 | common["file"] = "_files"; 99 | common["filename"] = "_files"; 100 | common["user"] = "_users"; 101 | common["username"] = "_users"; 102 | common["directory"] = "_directories"; 103 | common["path"] = "_directories"; 104 | common["url"] = "_urls"; 105 | } 106 | 107 | inline void ZshCompletionOutput::version(CmdLineInterface& _cmd) 108 | { 109 | std::cout << _cmd.getVersion() << std::endl; 110 | } 111 | 112 | inline void ZshCompletionOutput::usage(CmdLineInterface& _cmd ) 113 | { 114 | std::list argList = _cmd.getArgList(); 115 | std::string progName = _cmd.getProgramName(); 116 | std::string xversion = _cmd.getVersion(); 117 | theDelimiter = _cmd.getDelimiter(); 118 | basename(progName); 119 | 120 | std::cout << "#compdef " << progName << std::endl << std::endl << 121 | "# " << progName << " version " << _cmd.getVersion() << std::endl << std::endl << 122 | "_arguments -s -S"; 123 | 124 | for (ArgListIterator it = argList.begin(); it != argList.end(); it++) 125 | { 126 | if ( (*it)->shortID().at(0) == '<' ) 127 | printArg((*it)); 128 | else if ( (*it)->getFlag() != "-" ) 129 | printOption((*it), getMutexList(_cmd, *it)); 130 | } 131 | 132 | std::cout << std::endl; 133 | } 134 | 135 | inline void ZshCompletionOutput::failure( CmdLineInterface& _cmd, 136 | ArgException& e ) 137 | { 138 | static_cast(_cmd); // unused 139 | std::cout << e.what() << std::endl; 140 | } 141 | 142 | inline void ZshCompletionOutput::quoteSpecialChars( std::string& s ) 143 | { 144 | size_t idx = s.find_last_of(':'); 145 | while ( idx != std::string::npos ) 146 | { 147 | s.insert(idx, 1, '\\'); 148 | idx = s.find_last_of(':', idx); 149 | } 150 | idx = s.find_last_of('\''); 151 | while ( idx != std::string::npos ) 152 | { 153 | s.insert(idx, "'\\'"); 154 | if (idx == 0) 155 | idx = std::string::npos; 156 | else 157 | idx = s.find_last_of('\'', --idx); 158 | } 159 | } 160 | 161 | inline void ZshCompletionOutput::basename( std::string& s ) 162 | { 163 | size_t p = s.find_last_of('/'); 164 | if ( p != std::string::npos ) 165 | { 166 | s.erase(0, p + 1); 167 | } 168 | } 169 | 170 | inline void ZshCompletionOutput::printArg(Arg* a) 171 | { 172 | static int count = 1; 173 | 174 | std::cout << " \\" << std::endl << " '"; 175 | if ( a->acceptsMultipleValues() ) 176 | std::cout << '*'; 177 | else 178 | std::cout << count++; 179 | std::cout << ':'; 180 | if ( !a->isRequired() ) 181 | std::cout << ':'; 182 | 183 | std::cout << a->getName() << ':'; 184 | std::map::iterator compArg = common.find(a->getName()); 185 | if ( compArg != common.end() ) 186 | { 187 | std::cout << compArg->second; 188 | } 189 | else 190 | { 191 | std::cout << "_guard \"^-*\" " << a->getName(); 192 | } 193 | std::cout << '\''; 194 | } 195 | 196 | inline void ZshCompletionOutput::printOption(Arg* a, std::string mutex) 197 | { 198 | std::string flag = a->flagStartChar() + a->getFlag(); 199 | std::string name = a->nameStartString() + a->getName(); 200 | std::string desc = a->getDescription(); 201 | 202 | // remove full stop and capitalization from description as 203 | // this is the convention for zsh function 204 | if (!desc.compare(0, 12, "(required) ")) 205 | { 206 | desc.erase(0, 12); 207 | } 208 | if (!desc.compare(0, 15, "(OR required) ")) 209 | { 210 | desc.erase(0, 15); 211 | } 212 | size_t len = desc.length(); 213 | if (len && desc.at(--len) == '.') 214 | { 215 | desc.erase(len); 216 | } 217 | if (len) 218 | { 219 | desc.replace(0, 1, 1, tolower(desc.at(0))); 220 | } 221 | 222 | std::cout << " \\" << std::endl << " '" << mutex; 223 | 224 | if ( a->getFlag().empty() ) 225 | { 226 | std::cout << name; 227 | } 228 | else 229 | { 230 | std::cout << "'{" << flag << ',' << name << "}'"; 231 | } 232 | if ( theDelimiter == '=' && a->isValueRequired() ) 233 | std::cout << "=-"; 234 | quoteSpecialChars(desc); 235 | std::cout << '[' << desc << ']'; 236 | 237 | if ( a->isValueRequired() ) 238 | { 239 | std::string arg = a->shortID(); 240 | // Example arg: "[-A ] ..." 241 | size_t pos = arg.rfind(" ..."); 242 | 243 | if (pos != std::string::npos) { 244 | arg.erase(pos); 245 | } 246 | 247 | arg.erase(0, arg.find_last_of(theDelimiter) + 1); 248 | if ( arg.at(arg.length()-1) == ']' ) 249 | arg.erase(arg.length()-1); 250 | if ( arg.at(arg.length()-1) == ']' ) 251 | { 252 | arg.erase(arg.length()-1); 253 | } 254 | if ( arg.at(0) == '<' ) 255 | { 256 | arg.erase(arg.length()-1); 257 | arg.erase(0, 1); 258 | } 259 | size_t p = arg.find('|'); 260 | if ( p != std::string::npos ) 261 | { 262 | do 263 | { 264 | arg.replace(p, 1, 1, ' '); 265 | } 266 | while ( (p = arg.find_first_of('|', p)) != std::string::npos ); 267 | quoteSpecialChars(arg); 268 | std::cout << ": :(" << arg << ')'; 269 | } 270 | else 271 | { 272 | std::cout << ':' << arg; 273 | std::map::iterator compArg = common.find(arg); 274 | if ( compArg != common.end() ) 275 | { 276 | std::cout << ':' << compArg->second; 277 | } 278 | } 279 | } 280 | 281 | std::cout << '\''; 282 | } 283 | 284 | inline std::string ZshCompletionOutput::getMutexList( CmdLineInterface& _cmd, Arg* a) 285 | { 286 | XorHandler xorHandler = _cmd.getXorHandler(); 287 | std::vector< std::vector > xorList = xorHandler.getXorList(); 288 | 289 | if (a->getName() == "help" || a->getName() == "version") 290 | { 291 | return "(-)"; 292 | } 293 | 294 | ostringstream list; 295 | if ( a->acceptsMultipleValues() ) 296 | { 297 | list << '*'; 298 | } 299 | 300 | for ( int i = 0; static_cast(i) < xorList.size(); i++ ) 301 | { 302 | for ( ArgVectorIterator it = xorList[i].begin(); 303 | it != xorList[i].end(); 304 | it++) 305 | if ( a == (*it) ) 306 | { 307 | list << '('; 308 | for ( ArgVectorIterator iu = xorList[i].begin(); 309 | iu != xorList[i].end(); 310 | iu++ ) 311 | { 312 | bool notCur = (*iu) != a; 313 | bool hasFlag = !(*iu)->getFlag().empty(); 314 | if ( iu != xorList[i].begin() && (notCur || hasFlag) ) 315 | list << ' '; 316 | if (hasFlag) 317 | list << (*iu)->flagStartChar() << (*iu)->getFlag() << ' '; 318 | if ( notCur || hasFlag ) 319 | list << (*iu)->nameStartString() << (*iu)->getName(); 320 | } 321 | list << ')'; 322 | return list.str(); 323 | } 324 | } 325 | 326 | // wasn't found in xor list 327 | if (!a->getFlag().empty()) { 328 | list << "(" << a->flagStartChar() << a->getFlag() << ' ' << 329 | a->nameStartString() << a->getName() << ')'; 330 | } 331 | 332 | return list.str(); 333 | } 334 | 335 | } //namespace TCLAP 336 | #endif 337 | -------------------------------------------------------------------------------- /include/tclap/sstream.h: -------------------------------------------------------------------------------- 1 | // -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*- 2 | 3 | /****************************************************************************** 4 | * 5 | * file: sstream.h 6 | * 7 | * Copyright (c) 2003, Michael E. Smoot . 8 | * Copyright (c) 2004, Michael E. Smoot, Daniel Aarno . 9 | * Copyright (c) 2017 Google Inc. 10 | * All rights reserved. 11 | * 12 | * See the file COPYING in the top directory of this distribution for 13 | * more information. 14 | * 15 | * THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS 16 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | * DEALINGS IN THE SOFTWARE. 22 | * 23 | *****************************************************************************/ 24 | 25 | #ifndef TCLAP_SSTREAM_H 26 | #define TCLAP_SSTREAM_H 27 | 28 | #if !defined(HAVE_STRSTREAM) 29 | // Assume sstream is available if strstream is not specified 30 | // (https://sourceforge.net/p/tclap/bugs/23/) 31 | #define HAVE_SSTREAM 32 | #endif 33 | 34 | #if defined(HAVE_SSTREAM) 35 | #include 36 | namespace TCLAP { 37 | typedef std::istringstream istringstream; 38 | typedef std::ostringstream ostringstream; 39 | } 40 | #elif defined(HAVE_STRSTREAM) 41 | #include 42 | namespace TCLAP { 43 | typedef std::istrstream istringstream; 44 | typedef std::ostrstream ostringstream; 45 | } 46 | #else 47 | #error "Need a stringstream (sstream or strstream) to compile!" 48 | #endif 49 | 50 | #endif // TCLAP_SSTREAM_H 51 | -------------------------------------------------------------------------------- /src/beacon_data.h: -------------------------------------------------------------------------------- 1 | typedef struct _beacon_data 2 | { 3 | HMODULE hModule; 4 | HANDLE hBeacon; 5 | std::string name; 6 | std::vector breakpoints; 7 | std::vector args; 8 | std::map symbols; 9 | 10 | } beacon_data; -------------------------------------------------------------------------------- /src/beacondbg.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "beacondbg.h" 16 | #include "beacon_data.h" 17 | 18 | 19 | std::map beacons; 20 | 21 | beacondbg::beacondbg(std::istream& input, std::ostream &output) 22 | : in(input), out(output), pid(0) 23 | { 24 | 25 | } 26 | 27 | /// 28 | /// create a beacondbg session, locally or remote 29 | /// 30 | /// 31 | /// 32 | /// 33 | beacondbg * beacondbg::create(std::istream& input, std::ostream& output) 34 | { 35 | beacondbg* instance = new beacondbg(input, output); 36 | 37 | instance->setTargetPid(GetCurrentProcessId()); 38 | 39 | return instance; 40 | } 41 | 42 | typedef BOOL (WINAPI *RunBeacon_ptr)(HANDLE hBeacon, LPCSTR lpProcName, LPVOID lpData, SIZE_T Size); 43 | typedef HANDLE (WINAPI* LoadBeacon_ptr)(LPVOID lpData, SIZE_T Size); 44 | typedef BOOL(WINAPI* CloseBeacon_ptr)(HANDLE hBeacon); 45 | 46 | typedef BOOL(WINAPI* FindFirstSymbol_ptr)(HANDLE hBeacon, LPVOID* lpSymbolName, LPVOID* Address); 47 | 48 | bool beacondbg::load(const std::string beaconName, const std::vector &content) 49 | { 50 | if (beacons.find(beaconName) == beacons.end()) { 51 | HMODULE hModule = LoadLibraryA("beacon.dll"); 52 | if (hModule == NULL) { 53 | this->setError(BeaconError::CriticalError); 54 | return false; 55 | } 56 | 57 | LoadBeacon_ptr LoadBeacon = (LoadBeacon_ptr)GetProcAddress(hModule, "LoadBeacon"); 58 | 59 | HANDLE hBeacon = LoadBeacon((LPVOID)content.data(), content.size()); 60 | 61 | if (hBeacon != NULL) { 62 | beacons[beaconName].hModule = hModule; 63 | beacons[beaconName].name = beaconName; 64 | beacons[beaconName].hBeacon = hBeacon; 65 | beaconName_ = beaconName; 66 | this->setStatus(BeaconStatus::loaded); 67 | } 68 | else { 69 | this->setError(BeaconError::FileNotValid); 70 | } 71 | } 72 | 73 | return false; 74 | } 75 | 76 | bool beacondbg::loadArgs(const std::vector& content) 77 | { 78 | if (beacons.empty()) { 79 | this->setError(BeaconError::InvalidArguments); 80 | return false; 81 | } 82 | 83 | beacon_data &data = beacons.at(0); 84 | data.args = content; 85 | return true; 86 | } 87 | 88 | bool beacondbg::loadFromFile(const std::string &fileName) 89 | { 90 | std::ifstream input(fileName, std::ios::binary); 91 | 92 | if (!input) { 93 | std::string error = std::format("{} is not a valid path.", fileName); 94 | this->error(error); 95 | return false; 96 | } 97 | 98 | std::vector buffer(std::istreambuf_iterator(input), {}); 99 | 100 | size_t pathSeparator = fileName.find_last_of('\\'); 101 | size_t dotExtension = fileName.find_last_of('.'); 102 | 103 | if (pathSeparator == std::string::npos) { 104 | pathSeparator = 0; 105 | } 106 | else { 107 | pathSeparator++; 108 | } 109 | 110 | if (dotExtension == std::string::npos) { 111 | dotExtension = fileName.length(); 112 | } 113 | 114 | std::string beaconName = fileName.substr(pathSeparator, dotExtension - pathSeparator); 115 | 116 | return this->load(beaconName, buffer); 117 | } 118 | 119 | bool beacondbg::loadBofPack(const std::string& fileName) 120 | { 121 | std::ifstream input(fileName, std::ios::binary); 122 | 123 | if (!input) { 124 | std::string error = std::format("{} is not a valid path.", fileName); 125 | this->error(error); 126 | return false; 127 | } 128 | 129 | std::vector buffer(std::istreambuf_iterator(input), {}); 130 | 131 | return this->loadArgs(buffer); 132 | } 133 | 134 | bool beacondbg::unload(const std::string &name) 135 | { 136 | if (beacons.find(name) != beacons.end()) { 137 | beacon_data& beacon = beacons[name]; 138 | CloseBeacon_ptr CloseBeacon = (CloseBeacon_ptr)GetProcAddress(beacon.hModule, "CloseBeacon"); 139 | 140 | CloseBeacon(beacon.hBeacon); 141 | beacon.hBeacon = nullptr; 142 | beacons.erase(name); 143 | return true; 144 | } 145 | return false; 146 | } 147 | 148 | bool beacondbg::setTargetPid(uint32_t pid) 149 | { 150 | return false; 151 | } 152 | 153 | bool beacondbg::clearBreakPoint(void *address) 154 | { 155 | return false; 156 | } 157 | 158 | bool beacondbg::setBreakPoint(void *address) 159 | { 160 | return false; 161 | } 162 | 163 | /// 164 | /// run -> Invoke the beacon entry point 165 | /// 166 | /// 167 | /// 168 | /// 169 | bool beacondbg::run(std::string entryPoint, std::vector args) 170 | { 171 | unsigned char* beaconData = nullptr; size_t beaconSize = 0; 172 | 173 | if (beacons.find(beaconName_) == beacons.end()) { 174 | return false; 175 | } 176 | 177 | beacon_data& current_beacon = beacons[beaconName_]; 178 | 179 | RunBeacon_ptr RunBeacon = (RunBeacon_ptr)GetProcAddress(current_beacon.hModule, "RunBeacon"); 180 | 181 | if (args.size() == 0) { 182 | args = current_beacon.args; 183 | } 184 | 185 | RunBeacon(current_beacon.hBeacon, (char*)entryPoint.c_str(), args.data(), args.size()); 186 | return true; 187 | } 188 | 189 | extern void disassemble(uint64_t addr, beacon_data& beacon); 190 | 191 | bool beacondbg::disassemble(std::string symbol, std::vector args) 192 | { 193 | unsigned char* beaconData = nullptr; size_t beaconSize = 0; 194 | 195 | if (beacons.find(beaconName_) == beacons.end()) { 196 | this->error(std::format("{} undefined.", beaconName_)); 197 | return false; 198 | } 199 | 200 | beacon_data& current_beacon = beacons[beaconName_]; 201 | 202 | if (current_beacon.symbols.find(symbol) == current_beacon.symbols.end()) { 203 | this->error(std::format("symbol {} not found.", symbol)); 204 | return false; 205 | } 206 | 207 | ::disassemble((uint64_t)current_beacon.symbols[symbol], current_beacon); 208 | return true; 209 | } 210 | 211 | bool beacondbg::enumerateSymbols() 212 | { 213 | if (beacons.find(beaconName_) == beacons.end()) { 214 | return false; 215 | } 216 | 217 | beacon_data& current_beacon = beacons[beaconName_]; 218 | 219 | FindFirstSymbol_ptr FindFirstSymbol = (FindFirstSymbol_ptr)GetProcAddress(current_beacon.hModule, "FindFirstSymbol"); 220 | FindFirstSymbol_ptr FindNextSymbol = (FindFirstSymbol_ptr)GetProcAddress(current_beacon.hModule, "FindNextSymbol"); 221 | 222 | LPVOID SymbolName; LPVOID SymbolAddress; 223 | 224 | if (FindFirstSymbol(current_beacon.hBeacon, &SymbolName, &SymbolAddress)) do { 225 | if (SymbolAddress == NULL) 226 | continue; 227 | 228 | std::string line = std::format("\033[32m{}\t\033[31m0x{:x}", (const char*)SymbolName, (ULONG_PTR)SymbolAddress); 229 | this->println(line); 230 | 231 | current_beacon.symbols.insert({ std::string((const char*)SymbolName), (ULONG_PTR)SymbolAddress }); 232 | } while (FindNextSymbol(current_beacon.hBeacon, &SymbolName, &SymbolAddress)); 233 | 234 | this->print("\033[39m>"); 235 | } 236 | void beacondbg::print(const std::string fmt) 237 | { 238 | out << fmt; 239 | } 240 | 241 | void beacondbg::println(const std::string fmt) 242 | { 243 | out << fmt; 244 | 245 | if (!fmt.ends_with("\n")) 246 | out << std::endl; 247 | } 248 | 249 | void beacondbg::clear() 250 | { 251 | out << "\033[2J"; 252 | } 253 | 254 | void beacondbg::error(const std::string fmt) 255 | { 256 | out << "\033[31m" << fmt << "\033[39m" << std::endl; 257 | } 258 | 259 | bool beacondbg::prompt() 260 | { 261 | std::string msg; 262 | 263 | if (this->pid != 0) { 264 | msg += std::format("\033[32m{}\033[39m", this->pid); 265 | } 266 | 267 | if (this->beaconName_.length() > 0) { 268 | msg += std::format("\033[32m{}", this->beaconName_); 269 | } 270 | 271 | msg += "\033[39m>"; 272 | 273 | out << msg; 274 | return true; 275 | } 276 | std::string beacondbg::readln() 277 | { 278 | std::string line; 279 | std::getline(in, line); 280 | return line; 281 | } 282 | -------------------------------------------------------------------------------- /src/beacondbg.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 17.0 23 | Win32Proj 24 | {e1d26c06-4b54-4ce2-84f3-03c6d64fdc0e} 25 | beacondbg 26 | 10.0 27 | 28 | 29 | 30 | Application 31 | true 32 | v143 33 | Unicode 34 | 35 | 36 | Application 37 | false 38 | v143 39 | true 40 | Unicode 41 | 42 | 43 | Application 44 | true 45 | v143 46 | MultiByte 47 | 48 | 49 | Application 50 | false 51 | v143 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | $(SolutionDir)build\ 75 | $(SolutionDir)build\$(ProjectName)\ 76 | 77 | 78 | $(SolutionDir)build\ 79 | $(SolutionDir)build\$(ProjectName)\ 80 | 81 | 82 | $(SolutionDir)build\ 83 | $(SolutionDir)build\$(ProjectName)\ 84 | $(SolutionDir)deps\zydis\dependencies\zycore\include;$(SolutionDir)deps\zydis\include;$(SolutionDir)include\;$(VC_IncludePath);$(WindowsSDK_IncludePath) 85 | 86 | 87 | $(SolutionDir)build\ 88 | $(SolutionDir)build\$(ProjectName)\ 89 | $(SolutionDir)include\;$(VC_IncludePath);$(WindowsSDK_IncludePath); 90 | 91 | 92 | 93 | Level3 94 | true 95 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 96 | true 97 | 98 | 99 | Console 100 | true 101 | 102 | 103 | 104 | 105 | Level3 106 | true 107 | true 108 | true 109 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 110 | true 111 | 112 | 113 | Console 114 | true 115 | true 116 | true 117 | 118 | 119 | 120 | 121 | Level3 122 | true 123 | __BEACONDBG__;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 124 | true 125 | stdcpp20 126 | 127 | 128 | Console 129 | true 130 | $(SolutionDir)deps\zydis\msvc\bin\DebugX64\Zydis.lib;$(CoreLibraryDependencies);%(AdditionalDependencies) 131 | 132 | 133 | 134 | 135 | Level3 136 | true 137 | true 138 | true 139 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 140 | true 141 | stdcpp20 142 | MultiThreaded 143 | 144 | 145 | Console 146 | true 147 | true 148 | false 149 | $(CoreLibraryDependencies);%(AdditionalDependencies) 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | -------------------------------------------------------------------------------- /src/beacondbg.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | {424b28e7-cdc6-4434-8f8d-62580f8038ef} 18 | 19 | 20 | {d8319ab9-9115-49be-b351-0f0771b897d5} 21 | 22 | 23 | 24 | 25 | Source Files 26 | 27 | 28 | Source Files 29 | 30 | 31 | Source Files\cli 32 | 33 | 34 | Source Files\cli 35 | 36 | 37 | Source Files\cli 38 | 39 | 40 | Source Files\cli 41 | 42 | 43 | Source Files\cli 44 | 45 | 46 | Source Files\cli 47 | 48 | 49 | Source Files\cli 50 | 51 | 52 | Source Files\cli 53 | 54 | 55 | Source Files 56 | 57 | 58 | Source Files\cli 59 | 60 | 61 | 62 | 63 | Header Files\cli 64 | 65 | 66 | Header Files\cli 67 | 68 | 69 | Header Files\cli 70 | 71 | 72 | Header Files\cli 73 | 74 | 75 | Header Files\cli 76 | 77 | 78 | Header Files\cli 79 | 80 | 81 | Header Files\cli 82 | 83 | 84 | Header Files 85 | 86 | 87 | Header Files\cli 88 | 89 | 90 | -------------------------------------------------------------------------------- /src/cli/args.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "args.h" 7 | 8 | ArgsCommand::ArgsCommand(beacondbg* emu, std::vector args) 9 | { 10 | if (args.size() == 0) { 11 | emu->setError(BeaconError::InvalidArguments); 12 | return; 13 | } 14 | 15 | fileName_ = args.at(0); 16 | } 17 | 18 | bool ArgsCommand::onCommand(beacondbg* emu) 19 | { 20 | return emu->loadBofPack(fileName_); 21 | } 22 | -------------------------------------------------------------------------------- /src/cli/args.h: -------------------------------------------------------------------------------- 1 | #include "clicmd.h" 2 | 3 | class ArgsCommand : public CliCmd 4 | { 5 | public: 6 | ArgsCommand(beacondbg* emu, std::vector args); 7 | ~ArgsCommand() = default; 8 | 9 | bool onCommand(beacondbg* emu) override; 10 | 11 | private: 12 | std::string fileName_; 13 | }; 14 | -------------------------------------------------------------------------------- /src/cli/breakpoints.cpp: -------------------------------------------------------------------------------- 1 | #ifdef _WIN32 2 | #include 3 | #else 4 | typedef void* HANDLE; 5 | typedef void* LPVOID; 6 | #endif 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include "clicmd.h" 15 | #include "breakpoints.h" 16 | 17 | /// @brief BREAKPOINT holds basic informations about a breakpoint 18 | struct BREAKPOINT 19 | { 20 | HANDLE hProcess; /* hProcess => Remote process or current process breakpoint */ 21 | LPVOID lpAddress; 22 | std::string symbolName; /* breakpoint function name.. can be Library!SymbolName or SymbolName or just it's address */ 23 | }; 24 | 25 | Breakpoint::Breakpoint(beacondbg* emu, std::vector args) 26 | { 27 | if (args.size() == 0) { 28 | emu->setError(BeaconError::InvalidArguments); 29 | return; 30 | } 31 | 32 | if (emu->getStatus() != BeaconStatus::loaded) { 33 | emu->setError(BeaconError::InvalidStatus); 34 | return; 35 | } 36 | 37 | std::string address = args[0]; 38 | 39 | if (args[0].starts_with("0x")) { 40 | long addr = std::stoul(address, nullptr, 16); 41 | if (addr == 0) { 42 | emu->setError(BeaconError::InvalidAddress); 43 | } 44 | } 45 | } 46 | 47 | bool Breakpoint::onCommand(beacondbg *emu) 48 | { 49 | emu->error("bp not yet implemented"); 50 | return true; 51 | } 52 | 53 | template 54 | std::string Format(const std::string_view message, Args... formatItems) 55 | { 56 | return std::vformat(message, std::make_format_args(std::forward(formatItems)...)); 57 | } 58 | 59 | BreakpointList::BreakpointList(beacondbg* emu, std::vector args) 60 | { 61 | if (args.size() == 0) { 62 | //emu->setError(BeaconErrors::InvalidArguments); 63 | return; 64 | } 65 | 66 | } 67 | 68 | bool BreakpointList::onCommand(beacondbg *emu) 69 | { 70 | int i = 0; 71 | 72 | emu->println("Breakpoint list :"); 73 | 74 | for (BREAKPOINT* bp : breakpoints) 75 | { 76 | i++; 77 | std::string symbolName = bp->symbolName; 78 | 79 | // std::string_view Text = "[{:2}] at address {:x}"sv; 80 | 81 | std::string fmt = "[" + std::to_string(i) + "] at address " + symbolName; //Format(Text, i, symbolName); 82 | emu->println(fmt); 83 | } 84 | 85 | return true; 86 | } 87 | -------------------------------------------------------------------------------- /src/cli/breakpoints.h: -------------------------------------------------------------------------------- 1 | #include "clicmd.h" 2 | 3 | struct BREAKPOINT; 4 | 5 | class Breakpoint : public CliCmd 6 | { 7 | public: 8 | Breakpoint(beacondbg* emu, std::vector args); 9 | ~Breakpoint() = default; 10 | 11 | public: 12 | bool onCommand(beacondbg *emu) override; 13 | }; 14 | 15 | class BreakpointList : public CliCmd 16 | { 17 | friend class Breakpoint; 18 | 19 | public: 20 | BreakpointList(beacondbg *emu, std::vector args); 21 | ~BreakpointList() = default; 22 | 23 | void add(const Breakpoint &breakpoint); 24 | bool onCommand(beacondbg *emu) override; 25 | 26 | private: 27 | std::vector breakpoints; 28 | }; 29 | -------------------------------------------------------------------------------- /src/cli/cli.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "clicmd.h" 6 | #include "quit.h" 7 | #include "breakpoints.h" 8 | #include "load.h" 9 | #include "run.h" 10 | #include "args.h" 11 | #include "sym.h" 12 | #include "disasm.h" 13 | 14 | /** this function return true if the dbg has errors... */ 15 | static bool handleError(beacondbg* emu) 16 | { 17 | if (emu->getError() != BeaconError::none) { 18 | switch (emu->getError()) { 19 | case BeaconError::InvalidArguments: 20 | emu->error("Invalid syntax."); 21 | break; 22 | case BeaconError::FileNotFound: 23 | emu->error("File not found"); 24 | break; 25 | case BeaconError::EntryPointNotFound: 26 | emu->error("invalid entry point"); 27 | break; 28 | case BeaconError::InvalidAddress: 29 | emu->error("invalid address"); 30 | break; 31 | default: 32 | emu->error("Invalid error status."); 33 | break; 34 | } 35 | 36 | return true; 37 | } 38 | 39 | return false; 40 | } 41 | /// 42 | /// cli -> represents a session.. 43 | /// 44 | /// a beacondbg session (local or remote) 45 | /// 46 | int cli(beacondbg *emu) 47 | { 48 | CliData supportedCommands[10] = { 49 | { "help", "list of commands supported",[](beacondbg* emu, std::vector args) -> CliCmd* {return new Help(emu, args); }}, 50 | { "quit", "terminate session", [](beacondbg* emu, std::vector args) ->CliCmd* { return new Quit(emu, args); }}, 51 | { "bp", "set a breakpoint", [](beacondbg* emu, std::vector args) ->CliCmd* { return new Breakpoint(emu, args); }}, 52 | { "bl", "list all breakspoints", [](beacondbg* emu, std::vector args) ->CliCmd* { return new BreakpointList(emu, args); }}, 53 | { "load", "load a beacon in memory", [](beacondbg *emu, std::vector args)->CliCmd* { return new LoadCommand(emu, args); }}, 54 | { "unload", "unload a beacon from memory", [](beacondbg* emu, std::vector args)->CliCmd* { return new UnloadCommand(emu, args); }}, 55 | { "run", "run a beacon (start a session)", [](beacondbg* emu, std::vector args)->CliCmd* { return new RunCommand(emu, args); }}, 56 | { "args", "load arguments from file", [](beacondbg* emu, std::vector args)->CliCmd* { return new ArgsCommand(emu, args); }}, 57 | { "sym", "enumerate symbols of beacon", [](beacondbg* emu, std::vector args)->CliCmd* { return new SymCommand(emu, args); }}, 58 | { "u", "disassemble address", [](beacondbg* emu, std::vector args)->CliCmd* { return new DisasmCommand(emu, args); }} 59 | 60 | }; 61 | 62 | 63 | for (CliData& c : supportedCommands) 64 | CliCmd::registerCommand(&c); 65 | 66 | emu->setStatus(BeaconStatus::ready); 67 | 68 | while(emu->getStatus() != BeaconStatus::terminate) 69 | { 70 | emu->setError(BeaconError::none); 71 | 72 | emu->prompt(); 73 | std::string input = emu->readln(); 74 | 75 | std::vector args; 76 | 77 | std::optional opt = CliCmd::getCommand(input, args); 78 | 79 | if (!opt.has_value()) { 80 | if (input.size()) { 81 | std::string str = "Invalid command " + input; 82 | emu->println(str); 83 | } 84 | } else { 85 | CliCmd* cmd = (*opt)(emu, args); 86 | 87 | // process errors 88 | if (handleError(emu) == false) { 89 | cmd->onCommand(emu); 90 | handleError(emu); 91 | } 92 | delete cmd; 93 | } 94 | } 95 | 96 | return 0; 97 | } -------------------------------------------------------------------------------- /src/cli/clicmd.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "clicmd.h" 9 | 10 | static std::map commands; 11 | 12 | bool CliCmd::registerCommand(CliData *cmd) 13 | { 14 | commands[cmd->command] = cmd; 15 | return true; 16 | } 17 | 18 | bool CliCmd::registerCommand(std::initializer_list l) 19 | { 20 | for (CliData* c : l) 21 | registerCommand(c); 22 | 23 | return true; 24 | } 25 | 26 | std::optional CliCmd::getCommand(std::string input, std::vector &tokens) 27 | { 28 | if (input.size() == 0) 29 | return std::nullopt; 30 | 31 | // stringstream class check1 32 | std::stringstream check1(input); 33 | 34 | std::string intermediate; 35 | 36 | // Tokenizing w.r.t. space ' ' 37 | while(std::getline(check1, intermediate, ' ')) { 38 | tokens.push_back(intermediate); 39 | } 40 | 41 | std::map::iterator it = commands.find(tokens[0]); 42 | 43 | if (it == commands.end()) { 44 | return std::nullopt; 45 | } 46 | 47 | tokens.erase(tokens.begin()); 48 | 49 | return it->second->create; 50 | } 51 | 52 | Help::Help(beacondbg* emu, std::vector args) 53 | { 54 | 55 | } 56 | 57 | bool Help::onCommand(beacondbg *emu) 58 | { 59 | std::map::iterator it = commands.begin(); 60 | 61 | for (; it != commands.end(); it++) 62 | { 63 | std::string msg = std::format("\033[32m{}\t\033[39m{}", it->second->command, it->second->help); 64 | emu->println(msg); 65 | } 66 | return true; 67 | } 68 | -------------------------------------------------------------------------------- /src/cli/clicmd.h: -------------------------------------------------------------------------------- 1 | #ifndef __CLICMD_H_ 2 | #define __CLICMD_H_ 3 | 4 | #include 5 | #include 6 | 7 | class beacondbg; 8 | 9 | class CliCmd; 10 | 11 | typedef CliCmd* (*create_callback)(beacondbg* emu, std::vector args); 12 | 13 | struct CliData 14 | { 15 | std::string command; 16 | std::string help; 17 | create_callback create; 18 | }; 19 | 20 | class CliCmd 21 | { 22 | public: 23 | static bool registerCommand(std::initializer_list l); 24 | static bool registerCommand(CliData* cmd); 25 | static std::optional getCommand(std::string input, std::vector &args); 26 | 27 | public: 28 | virtual bool onCommand(beacondbg *emu) = 0; 29 | 30 | virtual ~CliCmd() = default; 31 | }; 32 | 33 | /** Help class share same object of clicmd.. they are accessing to the same data */ 34 | class Help : public CliCmd 35 | { 36 | public: 37 | Help(beacondbg *emu, std::vector args); 38 | ~Help() = default; 39 | 40 | bool onCommand(beacondbg *) override; 41 | }; 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /src/cli/disasm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "disasm.h" 9 | 10 | DisasmCommand::DisasmCommand(beacondbg* emu, std::vector args) 11 | { 12 | if (args.size() == 0) { 13 | emu->setError(BeaconError::InvalidArguments); 14 | return; 15 | } 16 | 17 | functionName_ = args.at(0); 18 | } 19 | 20 | bool DisasmCommand::onCommand(beacondbg* emu) 21 | { 22 | std::vector args; 23 | 24 | if (emu->disassemble(functionName_, args) == false) { 25 | emu->setError(BeaconError::EntryPointNotFound); 26 | return false; 27 | 28 | } 29 | emu->println(""); 30 | return true; 31 | } 32 | -------------------------------------------------------------------------------- /src/cli/disasm.h: -------------------------------------------------------------------------------- 1 | #include "clicmd.h" 2 | 3 | class DisasmCommand : public CliCmd 4 | { 5 | public: 6 | DisasmCommand(beacondbg* emu, std::vector args); 7 | ~DisasmCommand() = default; 8 | 9 | bool onCommand(beacondbg* emu) override; 10 | 11 | private: 12 | std::string functionName_; 13 | }; 14 | -------------------------------------------------------------------------------- /src/cli/load.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "load.h" 7 | 8 | LoadCommand::LoadCommand(beacondbg *emu, std::vector args) 9 | { 10 | if (args.size() == 0) { 11 | emu->setError(BeaconError::InvalidArguments); 12 | return; 13 | } 14 | 15 | fileName_ = args.at(0); 16 | } 17 | 18 | bool LoadCommand::onCommand(beacondbg *emu) 19 | { 20 | return emu->loadFromFile(fileName_); 21 | } 22 | 23 | UnloadCommand::UnloadCommand(beacondbg* emu, std::vector args) 24 | { 25 | if (args.size() == 0) { 26 | emu->setError(BeaconError::InvalidArguments); 27 | return; 28 | } 29 | 30 | beaconName_ = args.at(0); 31 | } 32 | 33 | bool UnloadCommand::onCommand(beacondbg* emu) 34 | { 35 | return emu->unload(this->beaconName_); 36 | } 37 | 38 | -------------------------------------------------------------------------------- /src/cli/load.h: -------------------------------------------------------------------------------- 1 | #include "clicmd.h" 2 | 3 | class LoadCommand : public CliCmd 4 | { 5 | public: 6 | LoadCommand(beacondbg *emu, std::vector args); 7 | ~LoadCommand() = default; 8 | 9 | bool onCommand(beacondbg *emu) override; 10 | 11 | private: 12 | std::string fileName_; 13 | }; 14 | 15 | class UnloadCommand : public CliCmd 16 | { 17 | public: 18 | UnloadCommand(beacondbg *emu, std::vector args); 19 | ~UnloadCommand() = default; 20 | 21 | bool onCommand(beacondbg* emu) override; 22 | private: 23 | std::string beaconName_; 24 | }; -------------------------------------------------------------------------------- /src/cli/quit.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "clicmd.h" 7 | #include "quit.h" 8 | 9 | Quit::Quit(beacondbg* emu, std::vector args) 10 | { 11 | 12 | } 13 | 14 | Quit::~Quit() 15 | { 16 | 17 | } 18 | 19 | bool Quit::onCommand(beacondbg *emu) 20 | { 21 | emu->setStatus(BeaconStatus::terminate); 22 | return true; 23 | } -------------------------------------------------------------------------------- /src/cli/quit.h: -------------------------------------------------------------------------------- 1 | #include "clicmd.h" 2 | 3 | class Quit 4 | : public CliCmd 5 | { 6 | public: 7 | Quit(beacondbg* emu, std::vector args); 8 | ~Quit(); 9 | 10 | bool onCommand(beacondbg *emu) override; 11 | }; 12 | -------------------------------------------------------------------------------- /src/cli/run.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "run.h" 9 | 10 | RunCommand::RunCommand(beacondbg* emu, std::vector args) 11 | { 12 | if (args.size() == 0) { 13 | emu->setError(BeaconError::InvalidArguments); 14 | return; 15 | } 16 | 17 | functionName_ = args.at(0); 18 | } 19 | 20 | bool RunCommand::onCommand(beacondbg* emu) 21 | { 22 | std::vector args; 23 | 24 | if (emu->run(functionName_, args) == false) { 25 | emu->setError(BeaconError::EntryPointNotFound); 26 | return false; 27 | 28 | } 29 | emu->println(""); 30 | return true; 31 | } 32 | -------------------------------------------------------------------------------- /src/cli/run.h: -------------------------------------------------------------------------------- 1 | #include "clicmd.h" 2 | 3 | class RunCommand : public CliCmd 4 | { 5 | public: 6 | RunCommand(beacondbg* emu, std::vector args); 7 | ~RunCommand() = default; 8 | 9 | bool onCommand(beacondbg* emu) override; 10 | 11 | private: 12 | std::string functionName_; 13 | }; 14 | -------------------------------------------------------------------------------- /src/cli/sym.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "clicmd.h" 7 | #include "sym.h" 8 | 9 | SymCommand::SymCommand(beacondbg* emu, std::vector args) 10 | { 11 | 12 | } 13 | 14 | SymCommand::~SymCommand() 15 | { 16 | 17 | } 18 | 19 | bool SymCommand::onCommand(beacondbg* emu) 20 | { 21 | if (emu->getStatus() == BeaconStatus::ready) { 22 | emu->error("no beacon loaded"); 23 | return false; 24 | } 25 | 26 | emu->enumerateSymbols(); 27 | return true; 28 | } -------------------------------------------------------------------------------- /src/cli/sym.h: -------------------------------------------------------------------------------- 1 | #include "clicmd.h" 2 | 3 | class SymCommand 4 | : public CliCmd 5 | { 6 | public: 7 | SymCommand(beacondbg* emu, std::vector args); 8 | ~SymCommand(); 9 | 10 | bool onCommand(beacondbg* emu) override; 11 | }; 12 | -------------------------------------------------------------------------------- /src/disassemble.cpp: -------------------------------------------------------------------------------- 1 | #define ZYDIS_STATIC_BUILD 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "beacondbg.h" 12 | #include "beacon_data.h" 13 | 14 | void disassemble(uint64_t addr, beacon_data& beacon) 15 | { 16 | CHAR data[4096]; 17 | 18 | SIZE_T NumberOfBytes; 19 | 20 | ReadProcessMemory(GetCurrentProcess(), (LPCVOID)addr, data, 4096, &NumberOfBytes); 21 | 22 | // Initialize decoder context 23 | ZydisDecoder decoder; 24 | ZydisDecoderInit(&decoder, ZYDIS_MACHINE_MODE_LONG_64, ZYDIS_STACK_WIDTH_64); 25 | 26 | // Initialize formatter. Only required when you actually plan to do instruction 27 | // formatting ("disassembling"), like we do here 28 | ZydisFormatter formatter; 29 | ZydisFormatterInit(&formatter, ZYDIS_FORMATTER_STYLE_INTEL); 30 | 31 | // Loop over the instructions in our buffer. 32 | // The runtime-address (instruction pointer) is chosen arbitrary here in order to better 33 | // visualize relative addressing 34 | ZyanU64 runtime_address = 0x007FFFFFFF400000; 35 | ZyanUSize offset = 0; 36 | const ZyanUSize length = 4096; 37 | ZydisDecodedInstruction instruction; 38 | ZydisDecodedOperand operands[ZYDIS_MAX_OPERAND_COUNT]; 39 | while (ZYAN_SUCCESS(ZydisDecoderDecodeFull(&decoder, data + offset, length - offset, 40 | &instruction, operands))) 41 | { 42 | // Print current instruction pointer. 43 | printf("%016" PRIX64 " ", runtime_address); 44 | 45 | // Format & print the binary instruction structure to human-readable format 46 | char buffer[256]; 47 | ZydisFormatterFormatInstruction(&formatter, &instruction, operands, 48 | instruction.operand_count_visible, buffer, sizeof(buffer), runtime_address, ZYAN_NULL); 49 | puts(buffer); 50 | 51 | offset += instruction.length; 52 | runtime_address += instruction.length; 53 | 54 | // stupid check.. 55 | if (data[offset] == 0x00 && data[offset + 1] == 0x00) break; 56 | } 57 | 58 | } -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | int main(int argc, char *argv[]) 9 | { 10 | TCLAP::CmdLine cmdLine("beacondbg", ' ', BEACONDBG_VERSION, true); 11 | 12 | TCLAP::ValueArg bof("B", "bof", "BOF input file", false, "beacon.obj", "file", cmdLine); 13 | TCLAP::ValueArg args("a", "args", "argument file", false, "beacon.dat", "file", cmdLine); 14 | 15 | cmdLine.parse(argc, argv); 16 | 17 | beacondbg* emu = beacondbg::create(std::cin, std::cout); 18 | 19 | if (bof.isSet()) { 20 | if (emu->loadFromFile(bof.getValue()) == false) { 21 | return -1; 22 | } 23 | } 24 | 25 | if (args.isSet()) { 26 | if (emu->loadBofPack(args.getValue()) == false) { 27 | return -1; 28 | } 29 | } 30 | std::thread t1(cli, emu); 31 | 32 | t1.join(); 33 | 34 | return 0; 35 | } -------------------------------------------------------------------------------- /static/disasm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolfcod/beacondbg/592999f7d87a6a96c8d95e9299cdd0c1889912b6/static/disasm.png -------------------------------------------------------------------------------- /tests/printf.c: -------------------------------------------------------------------------------- 1 | //#include 2 | #include "../include/beacon.h" 3 | 4 | void print(const char* str) 5 | { 6 | BeaconPrintf(CALLBACK_OUTPUT, str); 7 | } 8 | 9 | void go(unsigned char* argdata, int argsize) 10 | { 11 | print("Hello world!\n"); 12 | } -------------------------------------------------------------------------------- /tests/tests.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 17.0 23 | Win32Proj 24 | {af1dfc2e-3800-4bb7-8ee6-fe1e291f9bb5} 25 | tests 26 | 10.0 27 | 28 | 29 | 30 | Application 31 | true 32 | v143 33 | Unicode 34 | 35 | 36 | Application 37 | false 38 | v143 39 | true 40 | Unicode 41 | 42 | 43 | StaticLibrary 44 | true 45 | v143 46 | Unicode 47 | 48 | 49 | StaticLibrary 50 | false 51 | v143 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | $(SolutionDir)build\ 75 | $(SolutionDir)build\$(ProjectName)\ 76 | 77 | 78 | $(SolutionDir)build\ 79 | $(SolutionDir)build\$(ProjectName)\ 80 | 81 | 82 | 83 | Level3 84 | true 85 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 86 | true 87 | 88 | 89 | Console 90 | true 91 | 92 | 93 | 94 | 95 | Level3 96 | true 97 | true 98 | true 99 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 100 | true 101 | 102 | 103 | Console 104 | true 105 | true 106 | true 107 | 108 | 109 | 110 | 111 | Level3 112 | true 113 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 114 | true 115 | false 116 | Default 117 | 118 | 119 | Console 120 | true 121 | 122 | 123 | 124 | 125 | Level3 126 | true 127 | true 128 | true 129 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 130 | true 131 | 132 | 133 | Console 134 | true 135 | true 136 | true 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | -------------------------------------------------------------------------------- /tests/tests.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | -------------------------------------------------------------------------------- /vcpkg.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://raw.githubusercontent.com/microsoft/vcpkg-tool/main/docs/vcpkg.schema.json", 3 | "builtin-baseline": "edc84ff66e6262a9f7565c28eb76577aeab9c5aa", 4 | "dependencies": [ 5 | "fmt" 6 | ] 7 | } 8 | --------------------------------------------------------------------------------