Skip to content

Seat Management

SeatUpdater, SAS2, package install, startup, and recovery notes are consolidated here from the 2026-05-19 snapshot.

Deep-only retained findings

  • gitlab-master.nvidia.com/ngn-gia-storage/gfn/gameseat/seat-admin-service-2.0 and package subpaths are embedded in SAS2 symbols.

2026-05-19 application notes

AnalyzeGameStreamMergedLog.exe

What this program actually does

AnalyzeGameStreamMergedLog.exe is a py2exe-frozen Python 2.7 console utility that post-processes the merged GameStream log from GameStreamLogsMerger. It reads GameStreamLogs.log, applies line-level filtering (ignoreLineMatch, properLineMatch, properLogLines), and writes a trimmed output with a before/after line count summary.

Embedded strings confirm output format: Original Line Count: %d Trimmed Count: %d.

Runs as step 2 in post_session_backuplog.bat immediately after the merger step.


Architecture / control flow

post_session_backuplog.bat
  └─ python AnalyzeGameStreamMergedLog.py %AG_LOGS%\gslogs\GameStreamLogs.log
        ├─ open inputLogFilename (CLI arg 1)
        ├─ readlines / properLogLines loop
        ├─ ignoreLineMatch → drop noise lines
        ├─ properLineMatch / formedLine → keep useful lines
        └─ write GameStreamLogs_Trimmed.log
              └─ aws_log_uploader.py may upload gslogs/*

Embedded bytecode also contains GameStream/NSS certificate-validation strings (from bundled library code, not necessarily executed at runtime):

  • RegistryStorage.+InstallLocation; value: C:\\Program Files\\NVIDIA Corporation\\NvStreamSrvs>
  • Impersonating as NSS to validate SSAS and NSS certificates
  • SSAS and NSS already have consistent certificates

Windows API surface

CategoryAPIs (py2exe bootloader)
File I/OCreateFileA, CreateFileMappingA, GetFileSize, CloseHandle
MemoryVirtualAlloc, VirtualProtect, VirtualFree
Module loadLoadLibraryA, GetProcAddress, GetModuleHandleA
CRTMSVCR90.dll

Identical bootloader import surface to GameStreamLogsMerger.exe (shared py2exe stub).


PE metadata (readpe / radare2)

FieldValue
Pathservices/SeatUpdater/AnalyzeGameStreamMergedLog/AnalyzeGameStreamMergedLog.exe
FormatPE32 CUI; py2exe zip overlay
Architecturex86 (32-bit)
Size1,645,155 bytes
SHA-256bbf9e5a2584664e3fb235c76a01f75a8c22dd2fb6c17786055fdc8375079346
Bootloader timestampMon Nov 10 10:40:34 2008 (py2exe stub, not app build date)
Entry0x00402b28
CLRNone

Deployment and references

ItemEvidence
Orchestratorservices/SeatUpdater/post_session_backuplog.bat
Invocationc:\python27\python.exe %AG_HOME%\services\SeatUpdater\AnalyzeGameStreamMergedLog.py %AG_LOGS%\gslogs\GameStreamLogs.log > %AG_LOGS%\gslogs\GameStreamLogs_Trimmed.log
Input%AG_LOGS%\gslogs\GameStreamLogs.log
Output%AG_LOGS%\gslogs\GameStreamLogs_Trimmed.log
Pipeline orderMerger → Analyzer → exit code file
Sysmon allowlistC:\Asgard\services\SeatUpdater in NGN rules

Runtime evidence (logs)

No log in this snapshot references AnalyzeGameStreamMergedLog by name. Expected output GameStreamLogs_Trimmed.log is not present in captured %AG_LOGS%\gslogs\.


Not verified

  • Exact ignore/proper line regex or prefix lists (source .py not in workspace).
  • Whether trimmed or untrimmed log is uploaded by aws_log_uploader.py.
  • Production use of frozen .exe vs. python.exe + .py.

Evidence

  • readpe, r2_analyze.sh, strings on AnalyzeGameStreamMergedLog.exe
  • services/SeatUpdater/post_session_backuplog.bat

GameStreamLogsMerger.exe

What this program actually does

GameStreamLogsMerger.exe is a py2exe-frozen Python 2.7 console utility that collects scattered GameStream session logs from multiple on-seat locations (NvStreamer, NvStreamSvc, NSS, Steam, SSAS, NvBackend, GsUserPlugins) and merges them into a single chronological GameStreamLogs.log. It runs as step 1 of the SeatUpdater post-session log backup pipeline.

Deployment batch files invoke the .py source via c:\python27\python.exe; the frozen .exe is a self-contained alternate entry point with colocated python27.dll.


Architecture / control flow

post_session_backuplog.bat
  └─ python GamestreamLogsMerger.py -l 95 -o %AG_LOGS%\gslogs -u C:\users\kiosk
        ├─ argparse: -l (log level/percent), -o (output dir), -u (user profile)
        ├─ copyLogs / copylogfiles / appendLogFiles
        ├─ mergeAndSortLogs (timestamp-ordered merge)
        ├─ sanitizeBackendLogs (NvBackend-specific cleanup)
        └─ write GameStreamLogs.log
              └─ AnalyzeGameStreamMergedLog.py (downstream trim)

Embedded entry: GamestreamLogsMerger.py (note spelling). Bootloader from Jenkins path C:\Jenkins\snoopy_venv_2715\lib\site-packages\py2exe\boot_common.py.

Log source bitmask (embedded legend):

BitComponent
1NvStreamer
2NvStreamSvc
4NSS
8Steam
16SSAS
32NvBackend
64GsUserPlugins

Combinations like NvStreamer+NvStreamSvc(3) are supported.


Windows API surface

CategoryAPIs (py2exe bootloader)
File I/OCreateFileA, CreateFileMappingA, GetFileSize, CloseHandle, GetFullPathNameA
MemoryVirtualAlloc, VirtualProtect, VirtualFree, HeapAlloc, HeapFree
Module loadLoadLibraryA, GetProcAddress, GetModuleHandleA
ProcessCreateProcess, GetExitCodeProcess (embedded Python subprocess path)
CRTMSVCR90.dll (fprintf, malloc, getenv, atoi)

No direct network or WMI imports — pure filesystem log aggregation.


PE metadata (readpe / radare2)

FieldValue
Pathservices/SeatUpdater/GameStreamLogsMerger/GameStreamLogsMerger.exe
FormatPE32 CUI; file also reports Zip archive, with extra data prepended (py2exe overlay)
Architecturex86 (32-bit)
Size1,865,172 bytes
SHA-256187fd156d3de8d9c3bd1294e021ca6a1486394c7a3ee41422f2b9806a56d8f5e
Bootloader timestampThu Jun 18 10:45:59 2015
LinkerMSVC 9.0
Entry0x00402b28
CLRNone

Deployment and references

ItemEvidence
Orchestratorservices/SeatUpdater/post_session_backuplog.bat
Invocationc:\python27\python.exe %AG_HOME%\services\SeatUpdater\GamestreamLogsMerger.py -l 95 -o %AG_LOGS%\gslogs -u C:\users\kiosk
Merger log%AG_LOGS%\gslogs\gslogmerger.log
Output%AG_LOGS%\gslogs\GameStreamLogs.log
Exit code file%AG_HOME%\services\SeatUpdater\post_session_backuplog.ExitCode
Uploadaws_log_uploader.py glob includes %AG_LOGS%\gslogs\*.*
Sysmon allowlisttools/Sysmon/sysmon-ngn.xmlCommandLine contains C:\Asgard\services\SeatUpdater

Runtime evidence (logs)

No gslogmerger.log or GameStreamLogs.log captured in this workspace snapshot. No runtime log references the .exe by name — batch always invokes .py.

aws_log_uploader.py stops GridPerf before log upload (logman stop GridPerf) but does not reference the merger directly.


Not verified

  • Exact semantics of -l 95 (string (percent). appears near merger logic; likely log-level filter at 95%).
  • Full filesystem scan paths beyond -u C:\users\kiosk.
  • Whether production seats ever invoke the frozen .exe vs. always python.exe + .py.

Evidence

  • readpe, r2_analyze.sh, strings on GameStreamLogsMerger.exe
  • services/SeatUpdater/post_session_backuplog.bat, aws_log_uploader.py

SAS-2.0-windows-amd64.exe

What this program actually does

SAS-2.0-windows-amd64.exe is Seat Admin Service 2.0 — the first-boot orchestrator for a GeForce NOW gameseat. It mounts cloud-init metadata, parses seat identity and network userdata, configures multi-NIC Windows networking (APP / STREAM / STORAGE), syncs time, starts log shipping, validates Windows licensing, then pulls and installs the Pandora tenant stack from SMB storage servers.

It is invoked from sas2/start/startupchild.bat and reads sas2/config/sas2_config.json.

Source tree (strings): gitlab-master.nvidia.com/ngn-gia-storage/gfn/gameseat/seat-admin-service-2.0/
Build workspace path (strings): /home/jenkins/jenkins/workspace/SAS-2.0-Promotion/pkg/stages/


Architecture (from Go symbol strings)

SAS/main.go
  └─ stages/registry.go          — ordered stage runner
        ├─ stage_mount.go        — metadata CD / C:\Asgard\conf
        ├─ stage_metadata.go     — metadata.txt, networkdata, userdata
        ├─ stage_network.go      — GN2 adapter groups
        ├─ stage_timesync.go     — w32time
        ├─ stage_fluentbit.go    — remote log forwarding
        ├─ stage_license.go      — Windows activation check
        └─ stage_run.go          — Pandora install via SASSoftwareInstallerEXE
  └─ lib_metadata/, lib_network/, lib_license/, lib_run/
  └─ telemetry/                  — Kratos CloudEvents
  └─ sas_logger/                 — success/failure markers

Pipeline stages (from logs/sas2/sas2.log)

Stages appear as JSON "stage" fields. On success (2026-05-19 boot) they run in this order:

OrderStageSource fileBehavior (log evidence)
1mountstages/stage_mount.go, lib_mount/mount_windows.goScan drives for CDFS metadata CD; copy metadata, networkdata, userdata to C:\Asgard\conf; symlink userdata from ISO
2metadatastages/stage_metadata.go, lib_metadata/metadata.goRead metadata.txt, GN2 networkdata, userdata; emit Instance-ID / Zone / Pool to telemetry
3networklib_network/gn2_adapter_group_windows.goMatch NICs by MAC; rename to APP, STREAM, STORAGE; static IPs, routes, DNS, SMB Direct/multichannel, DSCP on STORAGE
4timesyncstages/stage_timesync.goStart/sync w32time
5fluentbitstages/stage_fluentbit.goWrite fluent-bit config; forward logs to logging server over TCP
6licenselib_license/license_windows.goCheck Windows Professional Workstation activation; skip if already activated
7runstages/stage_run.go, lib_run/run_windows.goProbe storage servers on TCP 445; invoke SASSoftwareInstallerEXE.exe for Pandora

Failure before metadata (May 8 boots): repeated SAS_MetadataParseFailedmetadata.txt missing when no CDFS drive present and C:\Asgard\conf empty.

Success marker: SAS 2.0 has successfully completed + Recorded SAS success (sas_logger/success_logger.go).


Stage details — successful boot timeline (2026-05-19)

Time (UTC)StageEvent
18:41:58mountFound CD D: CDFS; copied metadata to C:\Asgard\conf
18:41:58metadataInstance [REDACTED_INSTANCE_ID], pool [REDACTED_POOL], zone [REDACTED_ZONE]
18:41:58metadataSAS config flags: DisableVNC:true, SMBDirectStorage:true, LoggingOverTcp:true, EnableRsyslog:true, …
18:41:58–18:42:37networkAPP [REDACTED_IP], STREAM [REDACTED_IP], STORAGE [REDACTED_IP]; RoCE → SMB multichannel + SMB direct
18:42:37networkSeat successfully connected to the internet
18:42:40fluentbitLogging server [REDACTED_IP]; fluent-bit service started
18:42:43licenseWindows already activated (status 1) — skipped
18:42:43runStorage servers [REDACTED_IP],[REDACTED_IP],[REDACTED_IP] reachable
18:42:43runSASSoftwareInstallerEXE.exe C:\Asgard\sas2\bin\pandora_install_times.json sas2
18:43:25runStage complete; Kratos telemetry sent; SAS 2.0 has successfully completed

SAS error codes (strings)

CodeContext
SAS_MetadataParseFailedCannot read/parse seat metadata
SAS_ConfigurationFileNotFound / SAS_ConfigurationParseFailedConfig load failures
SAS_OSLicenseActivationFailedWindows activation
SAS_GPULicenseInitFailed / SAS_GPULicenseValidationFailedGPU licensing (not hit in sampled log)
SAS_RunLocalExecutableFailed / SAS_RunStorageServerExecutableFailedRun stage subprocess failures
SAS_GenericErrorCatch-all

Configuration

FileKeys (evidence)
sas2/config/sas2_config.jsonsas2_githash: 0d77c84, seat_type: gameseat, tenant_installer_source: storage-server, tenant_binary_path: C:\Asgard\pandora\dist\startup\startup.exe
Seat userdata (log)Storage server list, DNS servers, logging server IP, SAS feature flags
C:\Asgard\conf\metadata.txtInstance-ID, zone, pool
C:\Asgard\conf\networkdataGN2 link definitions (net1, net2, eth0)
C:\Asgard\conf\userdataSeat-level SAS toggles

Telemetry

Each failed or completed stage sends Kratos CloudEvents (telemetry/telemetry.go, telemetry/event_data.go). Boot time captured via telemetry/telemetry_windows.go.


Relationships

ComponentRole
SASSoftwareInstallerEXE.exeClones/mounts Pandora VHDX from SMB; runs B:\deploy\run.bat
LaunchProcessAsUser.exeReferenced in sas2 tree for user-context launches (not in successful run log)
gs2-agent, mb-repeaterStart later via Pandora/startup chain (~18:42:49+)
GSConfigurator (GSP)Not called by SAS directly; downstream services consume CSR configs

Not verified

  • Full ordered stage list in binary if config disables stages (only 7 stages seen in log).
  • GPU license stage — symbols exist; not executed in sampled successful run.
  • stage_example.go exists in build tree; not observed at runtime.

Evidence

  • strings on sas2/bin/SAS-2.0-windows-amd64.exe (docs/reverse-engineering/_analysis/SAS-2.0-windows-amd64.strings.txt)
  • logs/sas2/sas2.log
  • sas2/config/sas2_config.json
  • logs/sas2/SASSoftwareInstallerEXE.log

SASSoftwareInstallerEXE.exe

What this program actually does

SASSoftwareInstallerEXE.exe clones tenant software VHDX images from SMB storage servers, attaches them locally, runs each app's deploy\run.bat, records timing metrics, and cleans up VHDX files. Invoked by SAS 2.0 run stage:

SASSoftwareInstallerEXE.exe C:\Asgard\sas2\bin\pandora_install_times.json sas2

Pandora install timeline (from logs/sas2/SASSoftwareInstallerEXE.log)

TimeEvent
18:42:43Storage servers: [REDACTED_IP], [REDACTED_IP], [REDACTED_IP]
18:42:43Mount SMB \\[REDACTED_IP]\softwareA:\
18:42:43Clone VHDX pandora-main-dae006e-202655141656.vhdx to c:\asgard\vhdx\PANDORA\
18:42:43Attach → mount point B:\
18:42:43Run B:\deploy\run.bat → log pandoraSoftwareInstall.log (pid 4084)
18:43:24Success; detach/delete VHDX; write metrics JSON
18:43:25Metrics: clone 76 ms, mount 38 ms, install 41.3 s

Flags logged: directIOflag: 0, is_debug_seat: 0, skipping VDK App install (SAS 2.0 path).


Internal modules (log tags)

  • network_share — SMB share create/mount
  • disk_helper / disk_connector — VHDX open/attach/detach
  • ProcUtilWin32 — subprocess run/wait
  • win_helper — CIFS verify

Output artifacts

FilePurpose
C:\Asgard\sas2\bin\pandora_install_times.jsonInstall timing metrics
C:\Asgard\logs\sas2\pandoraSoftwareInstall.logPandora deploy stdout

Relationships

ComponentRole
SAS-2.0-windows-amd64.exeInvokes this during run stage
Pandora startup.exeDownstream tenant entry (per sas2_config.json)
gs2-agent, mb-repeaterInstalled as part of Pandora deploy chain

Evidence

  • logs/sas2/SASSoftwareInstallerEXE.log
  • logs/sas2/sas2.log (run stage invocation)
  • docs/reverse-engineering/_analysis/SASSoftwareInstallerEXE.strings.txt

LaunchProcessAsUser.exe

What this program actually does

LaunchProcessAsUser.exe is a small .NET Framework 4.8 console helper (OSL/Microsoft) that launches a child process under a specified Windows user account using supplied credentials. On Asgard seats, the sas2/bin copy is invoked by sas2/start/startup.bat to run startupchild.bat as the xen kiosk user from a scheduled-task context, bootstrapping SAS-2.0 without requiring an interactive login.

Perforce source: //sw/gcomp/dev/src/OSL/LaunchProcessAsUser/LaunchProcessAsUser/LaunchProcessAsUser/Program.cs (noted in startup.bat).


Architecture / control flow

startup.bat (kiosk scheduled task)
  └─ start /wait /b sas2\bin\launchprocessasuser "sas2\start\startupchild.bat"
        └─ _CorExeMain (mscoree.dll)
              └─ LaunchProcessAsUser.Main
                    ├─ RunAs(path, username, password, args, WorkingDirectory)
                    ├─ ExecuteCommandSync (stdout redirect variant)
                    ├─ ChangeUserPassword
                    └─ MakeSecureString → ProcessStartInfo → Process.Start → WaitForExit

Native PE is a thin CLR host stub; all logic is IL in the embedded assembly.


Windows API surface

LayerAPIs
Native stub_CorExeMain via mscoree.dll only
.NET (inferred)ProcessStartInfo, Process.Start, WaitForExit, RedirectStandardOutput, SecureString
Effective OSCreateProcessWithLogonW / CreateProcessAsUser (via CLR, not directly imported)

Credential parameter names in metadata: k_username/x_username, k_password/x_password (obfuscated CLI arg variants).

| r2 confirmed | _CorExeMain (mscoree.dll) |


PE metadata (readpe / radare2)

FieldValue
Pathsas2/bin/LaunchProcessAsUser.exe
FormatPE32 CUI, Mono/.NET assembly
Architecturex86 (32-bit)
Size8,704 bytes
SHA-256fd73ee2585570c2c34a80724ab04a9bb7fae83e8336dc3eb118335e91ccf31bb
CompiledWed Nov 22 00:03:24 2023
.NET targetv4.0.30319 / .NET Framework 4.8
Entry0x0040355ejmp _CorExeMain
ManifestrequestedExecutionLevel level="asInvoker"
PDB...\nmela\...\obj\x86\Debug\LaunchProcessAsUser.pdb

Deployment and references

ItemEvidence
Callersas2/start/startup.bat
Commandstart /wait /b %AG_HOME%\sas2\bin\launchprocessasuser "%AG_HOME%\sas2\start\startupchild.bat"
PurposeStart SAS 2.0 as xen user from kiosk scheduled task
Childstartupchild.bat masks log output for SAS bootstrap

No other config/script in this workspace references sas2/bin/LaunchProcessAsUser.exe by path.


Runtime evidence (logs)

No log file references LaunchProcessAsUser by name. SAS-2 activity appears in logs/sas2/ and logs/startup/startup.log without explicit attribution to this binary.


Comparison: sas2 vs tools copy

Propertysas2/bin (this file)tools/
Size8,704 B6,144 B
BuildDebug Nov 2023Release Mar 2015
.NET4.84 Client Profile
Extra methodsExecuteCommandSync, ChangeUserPasswordNot present
DeployedYesNo direct reference

Not verified

  • Exact CLI argument order (username, password, domain, executable, args) without decompiling Program.cs.
  • Whether ExecuteCommandSync captures stdout synchronously vs. fire-and-forget RunAs.

Evidence

  • readpe, r2_analyze.sh, strings on sas2/bin/LaunchProcessAsUser.exe
  • cmp/sha256sum vs. tools/LaunchProcessAsUser.exe
  • sas2/start/startup.bat

admindesk.top — Reversed & documented from Asgard rig backups and GCIS plugin binaries.