Welcome to hackvshack.net Forum!
Download Free HvH CS2/CS:GO Cheats, CFG, LUA/JS Scripts, and More!
Register

C++ Software CS2 Loader + web for cheats

Vortyk

Expert HvHer
User ID:
43664
Messages:
33
Reactions:
303
Badges:
9
REP:
−1/0+
Level:
101
Hi, everyone.
# C2-Loader — hardened loader

Console loader that pulls the build **from the auth server**, verifies it, and injects it.
No DLL is shipped next to the exe.

Code:
Expand Collapse Copy
```
cs2_loader/
  main.cpp             entry, menu, HTTP client, payload pipeline, injection
  harden.h             anti-reversing layer (strings, anti-debug, integrity, decision VM)
  strings.h            GENERATED - encrypted string pool
  tools/gen_strings.js generator for strings.h
  build_hardened.bat   release build (LTCG, no PDB, full mitigations)
  cs2_loader.exe       output
```

## Build

Code:
Expand Collapse Copy
```bat
node tools\gen_strings.js     :: only when you add or change a string
build_hardened.bat
```

Flags: `/O2 /GL /Gw /Gy /GS /guard:cf /Qspectre /sdl /DYNAMICBASE /GR- /W4 /WX`,
link `/LTCG /OPT:REF /OPT:ICF /DEBUG:NONE /PDB:NONE /HIGHENTROPYVA /CETCOMPAT /GUARD:CF`.

## Auxiliary commands

Code:
Expand Collapse Copy
```
cs2_loader.exe --selftest      SHA-256 vectors + decision VM + forged-signature rejection
cs2_loader.exe --stubs         run the remote-call stub in this process and verify it
cs2_loader.exe --mapcheck <dll> parse a PE and print sections/relocs/imports/TLS
cs2_loader.exe --hwid          machine fingerprint the server stores
cs2_loader.exe --api           endpoint in use
cs2_loader.exe --check <key>   one-shot auth, non-interactive
cs2_loader.exe --guard         integrity check bitmask (dev only, drop before release)
```

## Endpoint config — `api.txt` next to the exe

Code:
Expand Collapse Copy
```
host=auth.example.com
port=443
secure=1
```

Defaults are `127.0.0.1:8787`, plaintext.

## What the loader does on `[2]`

1. heartbeat — re-validate the license with the server (instant kill on revoke/expire)
2. decision gate — bytecode VM, see below
3. `GET /api/v1/payload?key=…&hwid=…` — downloads the active build
4. verify SHA-256 against the server header
5. verify the **RSA-2048 / SHA-256 signature** with the public key compiled into the binary
(the private key never leaves the server, so a patched server or a hand-made DLL cannot pass)
6. **manual map** the image into the target — headers, sections, relocations, imports,
TLS callbacks, section protections, `DllMain`
7. nothing is written to disk at any point; the buffer is wiped afterwards

## Manual map

| Step | Detail |
|---|---|
| base | preferred `ImageBase` when free (`VirtualQueryEx` probe), otherwise `VirtualAllocEx` anywhere; `delta` computed |
| headers | `SizeOfHeaders` bytes at the base |
| sections | each `SizeOfRawData` at `base + VirtualAddress` |
| relocations | `IMAGE_DIRECTORY_ENTRY_BASERELOC`, `IMAGE_REL_BASED_DIR64` only (x64) |
| imports | `IMAGE_DIRECTORY_ENTRY_IMPORT` (and delay-load when present); resolved locally when the target has the module at the same base, otherwise through a remote `GetProcAddress` |
| protections | `VirtualProtectEx` per section from its characteristics |
| TLS | `AddressOfCallBacks` rebased and invoked before `DllMain` (the static CRT registers one) |
| entry | `DllMain(base, DLL_PROCESS_ATTACH, 0)`; its return value is read back and treated as success |

A small position-independent stub (`ENDBR64` + 41 bytes) lives in the target and performs
the calls that must execute there. It is validated before use by calling `GetTickCount`
through it — a bad stub would otherwise take the game down.

Because the image is never handed to the loader, it does **not** appear in the target's
module list. Repeat injections inside one game session are caught with a cookie: a small
remote block holding a magic value and the mapped base, whose address is remembered in
`%LOCALAPPDATA%\CS2L\map_<pid>.bin`. Deleting that file defeats the check.

The DLL must be **x64**. Imports are resolved against the target, so a missing dependency
surfaces as `import <dllname>` rather than a silent failure.

## Anti-reversing layer (`harden.h`)

| Layer | What it does |
|---|---|
| String pool | every string XTEA-encrypted in `strings.h`, decrypted per use into a buffer that is `memset`-wiped on scope exit (`hz::Str`). `strings cs2_loader.exe` finds no `cs2.exe`, no API names, no endpoint paths. |
| Anti-debug | `PEB.BeingDebugged`, `NtQueryInformationProcess(ProcessDebugPort / ProcessDebugObjectHandle)`, `CheckRemoteDebuggerPresent`, the `OutputDebugString` + last-error trick, self-calibrated `rdtsc` vs `QueryPerformanceCounter` timing, `ThreadHideFromDebugger`. |
| Integrity | `kernel32`/`ntdll` must resolve from `%SystemRoot%\System32`, and the prologues of the six APIs the injector depends on must be unhooked (no `int3`, no `jmp`, no `ret`-stub). |
| Environment | FNV-1a hashed blocklist of debuggers / sandboxes, scanned across running processes. Recorded, not fatal by default (`guard.strict_env`). |
| Decision VM | the "licensed && !tampered && not expired" decision is bytecode executed by a tiny stack machine whose opcodes are re-keyed every launch (`seed = QPC ^ PID ^ rdtsc`), so it has a different byte signature on every run and cannot be located by pattern scanning. |
| Payload trust | RSA-2048 signature over the SHA-256 of the build — patching the loader is pointless because the server will not serve anything else. |

A detection never announces itself. It raises a flag, and the flag makes the VM gate return
"deny" — the process keeps running normally, which is what makes it hard to find the check.

### Adding a string

Add an entry to `tools/gen_strings.js`, run the generator, use `hz::Str(STR_ID)`.
Never put a literal in `main.cpp` — it will survive into the binary.

## Measured

* `strings` scan: no plaintext for target exe, endpoints, or API names
(only the imports the OS requires are visible, as always)
* `--selftest` green: SHA-256 vectors, all five VM gate outcomes, forged signature rejected
* `--stubs` green: stub calls `GetTickCount` and `lstrlenA` correctly, direct and via thread
* `--mapcheck` on the real `cs2.dll`: 10 sections, 59 relocation blocks / 8852 entries,
126 imports, TLS callbacks present
* end to end at the preferred base and at a relocated base: image mapped, `DllMain`
ran, staging directory empty, target alive
* second injection in the same session detected and refused
* `--guard` on a clean machine: `flags=0x0000`

## Limits — be honest about these

* A manual map is invisible to the module list but **very visible to memory scanners**:
anything walking the target's address space with `VirtualQueryEx` will find a private
region with a `MZ` header and a suspicious entry point. The loader's anti-RE work does
nothing for that — it belongs in the DLL.
* Cookie-based double-injection detection depends on a sidecar file. Delete it and the
loader will map a second copy.
* Anti-debug and integrity checks raise the cost of casual patching. A determined
reverser with time still gets there; VMProtect/Themida on top of this is the next step
if you want a higher floor.
* There is no packing: the `.text` section is normal code. `/O2 /GL` plus string
encryption is obfuscation, not packing.
* Anti-VM / sandbox detection is **off** by default on purpose — false positives cost you
paying customers.
# CS2 AUTH — license server + control panel

Zero dependencies. Node >= 18 (tested on Node 20). All data lives in `db.json`.

```
cs2_auth/
server.js HTTP server: loader API + admin API + static panel
config.json admin password hash + HMAC secret (created on first run)
db.json keys, bindings, login counters, event log, active build
keys/ RSA-2048 signing keypair (private key must stay on the server)
payloads/ uploaded builds
start.bat launcher
public/
index.html panel (login + dashboard + licenses + log)
style.css dark / crimson theme
app.js vanilla JS, no build step
```

## 1. Start

```bat
start.bat
REM or:
node server.js
REM or with your own password / port:
set ADMIN_PASS=my-password
set PORT=9000
node server.js
```

First run prints the admin password once (unless `ADMIN_PASS` is set).
Panel: ** — login `admin` + that password.

Default `HOST=0.0.0.0`, so the loader can reach it from other machines on the LAN
once you allow the port in the firewall:

```bat
netsh advfirewall firewall add rule name="CS2 Auth" dir=in action=allow protocol=TCP localport=8787
```

## 2. Panel

* **Dashboard** — tiles (total / active / lifetime / expired / unbound / online 24h /
logins 24h / denied 24h) and the issue form.
* **Issue license** — duration in days (`0` = lifetime), prefix, note, optional preset
HWID. If *bind to first machine* is on and no HWID is preset, the license binds to
whatever machine logs in first.
* **Licenses** — search + status filter, per-row: `COPY`, `+D` (extend),
`UNBIND` (free the machine), `REVOKE` / `RESTORE`, `DEL`.
* **Event log** — every login, bind, mismatch, revoke, issue, extend, delete.

A revoked or expired license is cut off on the next loader heartbeat (the loader
re-checks every 60 s and always right before injecting).

## 3. Build delivery (payload)

The DLL is **not** shipped with the loader. The loader downloads the active build from
the server, verifies its SHA-256 and its **RSA-2048 / SHA-256 signature**, stages it,
injects it and wipes the file. The private key lives only in `keys/private.pem`.

On first run the server generates `keys/` (RSA-2048) if it is missing.

### Panel → **Payload** tab

* Drag & drop (or browse) the compiled `.dll`
* Version, build note, "make this the active build"
* Active card: version, size, SHA-256, signature, download link, **force update** toggle
* History: activate / download / delete any previous build

`force update` sets `X-Force-Update: 1` so clients never run a stale cached build.

### How the loader consumes it

```
GET /api/v1/payload?key=…&hwid=…
200 + application/octet-stream
X-Payload-Version: 2.1.0
X-Payload-Sha256: 1b73e879…
X-Payload-Signature: <base64 RSA-2048/SHA-256 over the file>
X-Auth-Token: <hmac>
```

Failure modes: `401 invalid_key`, `403 revoked|expired|hwid_mismatch`, `404 no_payload`.

```
GET /api/v1/pubkey public key (JWK) for clients that want it
POST /api/admin/payload X-Payload-Version / -Note / -Filename / -Activate
GET /api/admin/payloads active build + history + force flag
POST /api/admin/payload/activate {version}
POST /api/admin/payload/force {force:true|false}
GET /api/admin/payload/:version/download
DELETE /api/admin/payload/:version
```

The upload endpoint rejects anything that is not a PE image (checks for the `MZ` header),
caps the size at 32 MB, signs the bytes and stores the file in `payloads/`.

### Regenerating the signing key

Delete `keys/private.pem` and `keys/public.pem` and restart. **Existing payloads keep
their old signatures** and the loader will reject them — re-upload every build after a
rotation. The loader binary has the public modulus compiled in (`tools/gen_strings.js`,
entries `P_PUB_N` / `P_PUB_E`), so a new key means a new loader build.

## 4. Loader API (what the exe calls)

| Endpoint | Purpose |
|---|---|
| `POST /api/v1/auth` | login: `{key, hwid, machine, version, ts}` → `{ok, reason, token, sub:{...}}` |
| `POST /api/v1/heartbeat` | keep-alive, re-issues the token, kills access if cut |
| `POST /api/v1/validate-token` | let the injected DLL verify `token` on its own |

`reason` on failure: `invalid_key`, `revoked`, `expired`, `hwid_mismatch`.

`token` = `HMAC-SHA256(secret, key|hwid|expires)`. The DLL can recompute it with the
same secret and refuse to run if it does not match.

## 5. Admin API

All under `/api/admin/*`, cookie session (`cs2_sid`, HttpOnly, 8 h), created by
`POST /api/admin/login {password}`.

```
GET /api/admin/stats
GET /api/admin/keys
POST /api/admin/keys {days, prefix?, note?, hwid?, lock_hwid?}
POST /api/admin/keys/:id/revoke | /unbind | /extend {days} | /note {note}
DELETE /api/admin/keys/:id
GET /api/admin/log
POST /api/admin/logout
```

## 6. Loader side

Put `api.txt` next to `cs2_loader.exe` when the server is not on localhost:

```
host=your.domain.com
port=443
secure=1
```

Defaults are `127.0.0.1:8787`. The loader ships the machine fingerprint
`sha256(MachineGuid + volume serial + salt)` — the raw serial never leaves the client,
but the raw MachineGuid is sent once as `machine` so you can recognise the box in the panel.

## 7. Before going public

1. **HTTPS.** Terminate TLS in front of the server — Caddy is one line:

```
auth.example.com {
reverse_proxy 127.0.0.1:8787
}
```

Then `secure=1` + `host=auth.example.com` in the loader's `api.txt`. Plain HTTP means
the key travels in clear text and anyone can replay it.

2. **Back up `db.json`** (and keep `config.json` — losing it invalidates every issued
token). The file is written atomically and re-read if you edit it by hand while the
server runs; a broken file is moved aside instead of being silently wiped.

3. **Change the admin password** — delete `config.json` and restart (a new one is
generated), or set `ADMIN_PASS` before starting.

## 8. Notes

* Single-process, single-file JSON store. Fine for hundreds/thousands of keys.
If you need multiple processes or >~100k keys, swap `loadDb`/`saveDb` for SQLite.
* Rate limiting is intentionally absent — put it in your reverse proxy if the panel
or the loader API is internet-facing.
* Password and key comparisons use `crypto.timingSafeEqual`.

credits: OpenAI, esoterik, llama, soufiw
 

Password for .zip file is hvh.net

Last edited by a moderator:

Who has read this thread (Total: 3) in last 1 hours View details