Skip to content

Commit 97a37aa

Browse files
committed
Synchronize the x64 example with hardened authentication and memory protection
1 parent 669ab3c commit 97a37aa

9 files changed

Lines changed: 623 additions & 132 deletions

File tree

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
name: Build C++ example
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
workflow_dispatch:
9+
inputs:
10+
app_name:
11+
description: Optional public KeyAuth application name
12+
required: false
13+
type: string
14+
owner_id:
15+
description: Optional public KeyAuth owner ID
16+
required: false
17+
type: string
18+
app_version:
19+
description: Optional application version
20+
required: false
21+
type: string
22+
23+
permissions:
24+
contents: read
25+
26+
env:
27+
KEYAUTH_LIBRARY_COMMIT: e345db830576b7a14cf1a818ffd4a3b368fb228b
28+
KEYAUTH_LIBRARY_SHA256: 93583a96377956b0092b6c037c5c258fc73881e694f57cff305ec658d62a5ab4
29+
30+
jobs:
31+
build:
32+
runs-on: windows-2022
33+
steps:
34+
- uses: actions/checkout@v4
35+
- uses: actions/checkout@v4
36+
with:
37+
repository: ELF-Nigel/keyauth-cpp-library-1.3API
38+
ref: ${{ env.KEYAUTH_LIBRARY_COMMIT }}
39+
path: .keyauth-source
40+
persist-credentials: false
41+
42+
- name: Verify paired library
43+
shell: pwsh
44+
run: |
45+
$expected = [IO.File]::ReadAllText('.keyauth-source/auth.hpp').Replace("`r`n", "`n")
46+
$actual = [IO.File]::ReadAllText('x64/lib/auth.hpp').Replace("`r`n", "`n")
47+
if ($actual -cne $expected) { throw 'Bundled header does not match the selected library source.' }
48+
$digest = (Get-FileHash -LiteralPath 'x64/library_x64.lib' -Algorithm SHA256).Hash.ToLowerInvariant()
49+
if ($digest -cne $env:KEYAUTH_LIBRARY_SHA256) { throw 'Bundled library does not match the verified build.' }
50+
51+
- uses: microsoft/setup-msbuild@v2
52+
53+
- name: Apply optional public application settings
54+
shell: pwsh
55+
env:
56+
APP_NAME: ${{ inputs.app_name }}
57+
OWNER_ID: ${{ inputs.owner_id }}
58+
APP_VERSION: ${{ inputs.app_version }}
59+
run: |
60+
if ([bool]$env:APP_NAME -ne [bool]$env:OWNER_ID) {
61+
throw 'Provide both application name and owner ID, or leave both blank.'
62+
}
63+
if ($env:OWNER_ID -and $env:OWNER_ID.Length -ne 10) {
64+
throw 'Owner ID must contain 10 characters.'
65+
}
66+
$source = Get-Content -LiteralPath 'x64/main.cpp' -Raw
67+
$settings = @{name = $env:APP_NAME; ownerid = $env:OWNER_ID; version = $env:APP_VERSION}
68+
foreach ($entry in $settings.GetEnumerator()) {
69+
if ([string]::IsNullOrEmpty($entry.Value)) { continue }
70+
$encoded = ([Text.Encoding]::UTF8.GetBytes($entry.Value) | ForEach-Object { '\x{0:x2}' -f $_ }) -join ''
71+
$replacement = 'std::string ' + $entry.Key + ' = skCrypt("' + $encoded + '").decrypt();'
72+
$pattern = '(?m)^std::string ' + $entry.Key + ' = skCrypt\("[^"\r\n]*"\)\.decrypt\(\);'
73+
if (-not [regex]::IsMatch($source, $pattern)) { throw 'Application setting was not found.' }
74+
$source = [regex]::Replace($source, $pattern, [Text.RegularExpressions.MatchEvaluator]{param($match) $replacement})
75+
}
76+
Set-Content -LiteralPath 'x64/main.cpp' -Value $source -NoNewline
77+
78+
- name: Build Release x64
79+
working-directory: x64
80+
run: msbuild example.vcxproj /t:Build /p:Configuration=Release /p:Platform=x64 /m
81+
82+
- name: Verify executable mitigations
83+
shell: pwsh
84+
run: |
85+
$installation = & "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath
86+
$dumpbin = Get-ChildItem -Path (Join-Path $installation 'VC/Tools/MSVC/*/bin/Hostx64/x64/dumpbin.exe') | Sort-Object FullName -Descending | Select-Object -First 1
87+
if (-not $dumpbin) { throw 'Executable inspection tool was not found.' }
88+
$headers = (& $dumpbin.FullName /headers /loadconfig 'x64/x64/Release/example.exe') -join "`n"
89+
if ($LASTEXITCODE -ne 0) { throw 'Executable inspection failed.' }
90+
foreach ($required in @('CF instrumented', 'FID table present', 'Dynamic base', 'NX compatible', 'High Entropy Virtual Addresses')) {
91+
if ($headers -notmatch [regex]::Escape($required)) { throw "Missing executable mitigation: $required" }
92+
}
93+
94+
- name: Package runnable example
95+
shell: pwsh
96+
run: |
97+
New-Item -ItemType Directory -Path build-output -Force | Out-Null
98+
Copy-Item -LiteralPath 'x64/x64/Release/example.exe' -Destination build-output
99+
$installation = & "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath
100+
$crt = Get-ChildItem -Path (Join-Path $installation 'VC/Redist/MSVC/*/x64/Microsoft.VC*.CRT') -Directory | Sort-Object FullName -Descending | Select-Object -First 1
101+
if (-not $crt) { throw 'Visual C++ runtime files were not found.' }
102+
Get-ChildItem -LiteralPath $crt.FullName -Filter '*.dll' | Copy-Item -Destination build-output
103+
Get-FileHash -LiteralPath 'build-output/example.exe' -Algorithm SHA256 | ForEach-Object { $_.Hash.ToLowerInvariant() + ' example.exe' } | Set-Content -LiteralPath 'build-output/SHA256SUMS.txt'
104+
105+
- uses: actions/upload-artifact@v4
106+
with:
107+
name: KeyAuth-CPP-Example-x64
108+
path: build-output/
109+
if-no-files-found: error
110+
retention-days: 30

‎x64/auth_guard.hpp‎

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,7 @@
11
#pragma once
2+
#include "auth.hpp"
23

3-
#include <Windows.h>
4-
#include <string>
5-
6-
inline void checkAuthenticated(const std::string& ownerid) {
7-
while (true) {
8-
if (GlobalFindAtomA(ownerid.c_str()) == 0) {
9-
exit(13);
10-
}
11-
Sleep(1000);
12-
}
4+
inline bool checkAuthenticated(KeyAuth::api& app) {
5+
app.check();
6+
return app.response.success && app.authenticated();
137
}

‎x64/example.vcxproj‎

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -125,14 +125,15 @@
125125
<ClCompile>
126126
<WarningLevel>Level3</WarningLevel>
127127
<SDLCheck>true</SDLCheck>
128-
<PreprocessorDefinitions>CURL_STATICLIB;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
128+
<PreprocessorDefinitions>CURL_STATICLIB;SODIUM_STATIC;NDEBUG;_ITERATOR_DEBUG_LEVEL=0;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
129129
<ConformanceMode>true</ConformanceMode>
130-
<LanguageStandard>stdcpp20</LanguageStandard>
130+
<LanguageStandard>stdcpp17</LanguageStandard>
131+
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
131132
</ClCompile>
132133
<Link>
133134
<SubSystem>Console</SubSystem>
134135
<GenerateDebugInformation>true</GenerateDebugInformation>
135-
<AdditionalDependencies>libcurl.lib;libsodium.lib;%(AdditionalDependencies)</AdditionalDependencies>
136+
<AdditionalDependencies>library_x64.lib;zlib.lib;winhttp.lib;%(AdditionalDependencies)</AdditionalDependencies>
136137
</Link>
137138
</ItemDefinitionGroup>
138139
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@@ -141,6 +142,8 @@
141142
<FunctionLevelLinking>true</FunctionLevelLinking>
142143
<IntrinsicFunctions>true</IntrinsicFunctions>
143144
<SDLCheck>true</SDLCheck>
145+
<ControlFlowGuard>Guard</ControlFlowGuard>
146+
<BufferSecurityCheck>true</BufferSecurityCheck>
144147
<PreprocessorDefinitions>CURL_STATICLIB;SODIUM_STATIC;_CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
145148
<ConformanceMode>true</ConformanceMode>
146149
<LanguageStandard>stdcpp17</LanguageStandard>
@@ -149,10 +152,14 @@
149152
</ClCompile>
150153
<Link>
151154
<SubSystem>Console</SubSystem>
155+
<AdditionalOptions>/GUARD:CF %(AdditionalOptions)</AdditionalOptions>
156+
<RandomizedBaseAddress>true</RandomizedBaseAddress>
157+
<HighEntropyVA>true</HighEntropyVA>
158+
<DataExecutionPrevention>true</DataExecutionPrevention>
152159
<EnableCOMDATFolding>true</EnableCOMDATFolding>
153160
<OptimizeReferences>true</OptimizeReferences>
154161
<GenerateDebugInformation>false</GenerateDebugInformation>
155-
<AdditionalDependencies>libcurl.lib;zlib.lib;libsodium.lib;winhttp.lib;%(AdditionalDependencies)</AdditionalDependencies>
162+
<AdditionalDependencies>library_x64.lib;zlib.lib;winhttp.lib;%(AdditionalDependencies)</AdditionalDependencies>
156163
<TargetMachine>MachineX64</TargetMachine>
157164
</Link>
158165
</ItemDefinitionGroup>

0 commit comments

Comments
 (0)