├── .gitignore ├── .gitmodules ├── CSteamAPI.h ├── IClientParentalSettings.h ├── LICENSE ├── Makefile ├── README.md ├── protoreader.cpp ├── protoreader.h ├── spprt.cpp └── utlbuffer_mini.h /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.obj 3 | *.exe 4 | *.bin 5 | *.bat 6 | Makefile.all 7 | tests/ 8 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "3rdparty/OSW"] 2 | path = 3rdparty/OSW 3 | url = git@github.com:m4dEngi/open-steamworks.git 4 | branch = master 5 | [submodule "3rdparty/scrypt-jane"] 6 | path = 3rdparty/scrypt-jane 7 | url = git@github.com:floodyberry/scrypt-jane.git 8 | branch = master 9 | -------------------------------------------------------------------------------- /CSteamAPI.h: -------------------------------------------------------------------------------- 1 | #ifndef CSTEAMAPI_H 2 | #define CSTEAMAPI_H 3 | 4 | #pragma once 5 | 6 | #include "./3rdparty/OSW/OpenSteamworks/Steamworks.h" 7 | #include "./3rdparty/OSW/OpenSteamAPI/src/Interface_OSW.h" 8 | 9 | class CSteamAPI 10 | { 11 | public: 12 | CSteamAPI() 13 | : hPipe(0), hUser(0), m_pClientEngine(nullptr), m_pSteamClient(nullptr), 14 | Friends(nullptr), User(nullptr), UnifiedMessages(nullptr), ParentalSettings(nullptr) 15 | { 16 | loader = new CSteamAPILoader(); 17 | } 18 | 19 | ~CSteamAPI() 20 | { 21 | if (hPipe && hUser) 22 | { 23 | m_pSteamClient->ReleaseUser(hPipe, hUser); 24 | m_pSteamClient->BReleaseSteamPipe(hPipe); 25 | m_pSteamClient->BShutdownIfAllPipesClosed(); 26 | } 27 | delete loader; 28 | } 29 | 30 | bool Load() 31 | { 32 | if (!loader->Load()) 33 | return false; 34 | 35 | DynamicLibrary m_pTier0("tier0_s"); // x64 ??? 36 | Tier0_Log = (decltype(Tier0_Log)) m_pTier0.GetSymbol("Log"); 37 | Tier0_Msg = (decltype(Tier0_Msg)) m_pTier0.GetSymbol("Msg"); 38 | Tier0_Warning = (decltype(Tier0_Warning)) m_pTier0.GetSymbol("Warning"); 39 | Tier0_Plat_RelativeTicks = (decltype(Tier0_Plat_RelativeTicks)) m_pTier0.GetSymbol("Plat_RelativeTicks"); 40 | Tier0_Plat_TickDiffMilliSec = (decltype(Tier0_Plat_TickDiffMilliSec)) m_pTier0.GetSymbol("Plat_TickDiffMilliSec"); 41 | 42 | return Tier0_Log && Tier0_Msg; 43 | } 44 | 45 | bool Connect() 46 | { 47 | CreateInterfaceFn factory = loader->GetSteam3Factory(); 48 | if (!factory) 49 | return false; 50 | 51 | m_pClientEngine = (IClientEngine *)factory(CLIENTENGINE_INTERFACE_VERSION, NULL); 52 | m_pSteamClient = (ISteamClient017 *)factory(STEAMCLIENT_INTERFACE_VERSION_017, NULL); 53 | if (!m_pSteamClient) 54 | return false; 55 | 56 | hPipe = m_pSteamClient->CreateSteamPipe(); 57 | hUser = m_pSteamClient->ConnectToGlobalUser(hPipe); 58 | if (!hPipe || !hUser) 59 | return false; 60 | 61 | Friends = (ISteamFriends015 *)m_pSteamClient->GetISteamFriends(hUser, hPipe, STEAMFRIENDS_INTERFACE_VERSION_015); 62 | User = (ISteamUser019 *)m_pSteamClient->GetISteamUser(hUser, hPipe, STEAMUSER_INTERFACE_VERSION_019); 63 | UnifiedMessages = (ISteamUnifiedMessages001 *)m_pSteamClient->GetISteamUnifiedMessages(hUser, hPipe, STEAMUNIFIEDMESSAGES_INTERFACE_VERSION_001); 64 | 65 | if (m_pClientEngine) 66 | { 67 | // ugly hack, but I am too lazy to fix it in the original repository 68 | ParentalSettings = (m_pClientEngine->*(IClientParentalSettings *(IClientEngine::*)(HSteamPipe, const char *))&m_pClientEngine->GetIClientParentalSettings)(hPipe, NULL); 69 | if (!ParentalSettings) // this mean vtable is changed (very old or very new steam client) 70 | { 71 | // fix the stack pointer 72 | #if defined(_MSC_VER) 73 | __asm {subl $4,%esp} 74 | #elif defined(__GNUC__) 75 | asm ("subl $4,%esp"); 76 | #else 77 | // ..or not. not my problem. 78 | #endif 79 | } 80 | } 81 | 82 | return Friends && User && UnifiedMessages; 83 | } 84 | 85 | private: 86 | CSteamAPILoader *loader; 87 | HSteamPipe hPipe; 88 | HSteamUser hUser; 89 | IClientEngine *m_pClientEngine; 90 | ISteamClient017 *m_pSteamClient; 91 | 92 | public: 93 | ISteamFriends015 *Friends; 94 | ISteamUser019 *User; 95 | ISteamUnifiedMessages001 *UnifiedMessages; 96 | IClientParentalSettings *ParentalSettings; 97 | 98 | void (STEAM_CALL *Tier0_Log)(const char *szFormat, ...); 99 | void (STEAM_CALL *Tier0_Msg)(const char *szFormat, ...); 100 | void (STEAM_CALL *Tier0_Warning)(const char *szFormat, ...); 101 | uint64 (STEAM_CALL *Tier0_Plat_RelativeTicks)(); 102 | int32 (STEAM_CALL *Tier0_Plat_TickDiffMilliSec)(uint64 tickStart, uint64 tickEnd); 103 | }; 104 | 105 | #endif // CSTEAMAPI_H 106 | -------------------------------------------------------------------------------- /IClientParentalSettings.h: -------------------------------------------------------------------------------- 1 | //========================== Open Steamworks ================================ 2 | // 3 | // This file is part of the Open Steamworks project. All individuals associated 4 | // with this project do not claim ownership of the contents 5 | // 6 | // The code, comments, and all related files, projects, resources, 7 | // redistributables included with this project are Copyright Valve Corporation. 8 | // Additionally, Valve, the Valve logo, Half-Life, the Half-Life logo, the 9 | // Lambda logo, Steam, the Steam logo, Team Fortress, the Team Fortress logo, 10 | // Opposing Force, Day of Defeat, the Day of Defeat logo, Counter-Strike, the 11 | // Counter-Strike logo, Source, the Source logo, and Counter-Strike Condition 12 | // Zero are trademarks and or registered trademarks of Valve Corporation. 13 | // All other trademarks are property of their respective owners. 14 | // 15 | //============================================================================= 16 | 17 | #ifndef ICLIENTPARENTALSETTINGS_H 18 | #define ICLIENTPARENTALSETTINGS_H 19 | #ifdef _WIN32 20 | #pragma once 21 | #endif 22 | 23 | #include "SteamTypes.h" 24 | 25 | abstract_class UNSAFE_INTERFACE IClientParentalSettings 26 | { 27 | public: 28 | virtual bool BIsParentalLockEnabled() = 0; 29 | virtual bool BIsParentalLockLocked() = 0; 30 | virtual bool BIsAppBlocked( AppId_t unAppID ) = 0; 31 | virtual bool BIsAppInBlockList( AppId_t unAppID ) = 0; 32 | virtual bool BIsFeatureBlocked( EParentalFeature eParentalFeature ) = 0; 33 | virtual bool BIsFeatureInBlockList( EParentalFeature eParentalFeature ) = 0; 34 | virtual bool BGetSerializedParentalSettings( CUtlBuffer * pBuffer ) = 0; 35 | virtual bool BGetRecoveryEmail(char*, int) = 0; 36 | }; 37 | 38 | #endif // ICLIENTPARENTALSETTINGS_H 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Alexey A. Krasnov 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 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | GCC = gcc 2 | GXX = g++ 3 | INCLUDE_PATH = "./3rdparty/OSW/OpenSteamworks" 4 | 5 | CFLAGS = -Wall -Wextra -Wshadow -m32 -O2 -pipe -fno-ident -fno-exceptions -I$(INCLUDE_PATH) 6 | CFLAGS += -DSTEAMWORKS_CLIENT_INTERFACES -DNO_CSTEAMID_STL -DSCRYPT_SALSA -DSCRYPT_SHA256 -DSCRYPT_TEST 7 | CFLAGS += -Wformat-security -Wno-unused-function -Wno-unused-variable -Wno-unused-but-set-variable -Wunreachable-code 8 | CPPFLAGS = $(CFLAGS) -nostdinc++ -std=c++11 9 | LDFLAGS = -s -static 10 | 11 | SOURCES_SPPRT = spprt.cpp \ 12 | protoreader.cpp \ 13 | 3rdparty\OSW\OpenSteamAPI\src\Interface_OSW.cpp 14 | 15 | SOURCES_SCRYPT = 3rdparty\scrypt-jane\scrypt-jane.c 16 | 17 | OBJECTS_SPPRT = $(SOURCES_SPPRT:.cpp=.o) 18 | #OBJECTS_SCRYPT = $(SOURCES_SCRYPT:.c=.o) 19 | TARGET_SPPRT = spprt.exe 20 | 21 | .PHONY: all clean 22 | 23 | .SUFFIXES: .cpp .c .o 24 | 25 | all: $(TARGET_SPPRT) 26 | 27 | $(TARGET_SPPRT): $(OBJECTS_SPPRT) $(OBJECTS_SCRYPT) 28 | $(GXX) $(OBJECTS_SPPRT) $(OBJECTS_SCRYPT) $(CPPFLAGS) $(LDFLAGS) -o $@ 29 | 30 | .cpp.o: 31 | $(GXX) $(CPPFLAGS) -c $< -o $@ 32 | 33 | .c.o: 34 | $(GCC) $(CFLAGS) -c $< -o $@ 35 | 36 | clean: 37 | del $(TARGET_SPPRT) $(OBJECTS_SPPRT) $(OBJECTS_SCRYPT) 38 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Steam Parental Pin Recovery Tool (SPPRTool) 2 | SPPRTool is using to recover Steam Family View PIN code without the need to use email if it is not set or not available. 3 | 4 | ## Disclaimer 5 | _This software is not intended to gain unauthorized access to Steam account in any case. Use it at your own risk and only with the permission of the owner of the account._ 6 | -------------------------------------------------------------------------------- /protoreader.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * MIT License 3 | * 4 | * Copyright (c) 2017 Nephrite 5 | */ 6 | 7 | #include // memmove 8 | 9 | unsigned int ReadProtoNumber(const unsigned char *pubInput, unsigned int cubAvail, void *pubDest, unsigned int cubSize, bool bFixed = false) 10 | { 11 | if (bFixed) 12 | { 13 | switch (cubSize) 14 | { 15 | case 1: 16 | *(unsigned char *)pubDest = *pubInput; 17 | break; 18 | case 2: 19 | *(unsigned short *)pubDest = *(unsigned short *)pubInput; 20 | break; 21 | case 4: 22 | *(unsigned int *)pubDest = *(unsigned int *)pubInput; 23 | break; 24 | case 8: 25 | *(unsigned long long *)pubDest = *(unsigned long long *)pubInput; 26 | break; 27 | default: 28 | return 0; 29 | } 30 | 31 | return cubSize; 32 | } 33 | 34 | union 35 | { 36 | char result8; 37 | short result16; 38 | int result32; 39 | long long result64 = 0; 40 | }; 41 | 42 | unsigned int bytes_read = 0; 43 | 44 | while (bytes_read < cubAvail) 45 | { 46 | switch (cubSize) 47 | { 48 | case 1: 49 | case 2: 50 | case 3: 51 | case 4: 52 | result32 |= (pubInput[bytes_read] & 0x7F) << (bytes_read * 7); 53 | break; 54 | case 5: 55 | case 6: 56 | case 7: 57 | case 8: 58 | case 9: 59 | case 10: 60 | result64 |= (long long)(pubInput[bytes_read] & 0x7F) << (bytes_read * 7); 61 | break; 62 | default: 63 | break; 64 | } 65 | if ((pubInput[bytes_read++] & 0x80) == 0) { 66 | break; 67 | } 68 | } 69 | 70 | if (pubDest) 71 | { 72 | switch (cubSize) 73 | { 74 | case 1: 75 | *(char *)pubDest = result8; 76 | break; 77 | case 2: 78 | *(short *)pubDest = result16; 79 | break; 80 | case 4: 81 | *(int *)pubDest = result32; 82 | break; 83 | case 8: 84 | *(long long *)pubDest = result64; 85 | break; 86 | default: 87 | if (result64 >> 32) 88 | *(long long *)pubDest = result64; 89 | else 90 | *(int *)pubDest = result32; 91 | } 92 | } 93 | 94 | return bytes_read; 95 | } 96 | 97 | unsigned int ReadProtoLengthDelimited(const unsigned char *pubInput, unsigned int cubAvail, void *pubDest = NULL, unsigned int *cubSize = NULL) 98 | { 99 | unsigned int bytes_read = 0; 100 | unsigned int length = 0; 101 | 102 | bytes_read = ReadProtoNumber(pubInput, cubAvail, &length, 4); 103 | cubAvail -= bytes_read; 104 | 105 | unsigned int max_size_to_read = (length <= cubAvail) ? length : cubAvail; 106 | unsigned int size_to_copy = max_size_to_read; 107 | 108 | if (cubSize) 109 | { 110 | size_to_copy = (*cubSize == 0 || max_size_to_read <= *cubSize) ? max_size_to_read : *cubSize; 111 | *cubSize = length; 112 | } 113 | if (pubDest && size_to_copy) 114 | { 115 | memmove(pubDest, pubInput + bytes_read, size_to_copy); 116 | } 117 | 118 | return bytes_read + max_size_to_read; 119 | } 120 | 121 | unsigned int ReadProtoField(const unsigned char *pubInput, unsigned int cubAvail, unsigned int *punTag, unsigned int *punWireType, void *pubDest = NULL, unsigned int *cubSize = NULL) 122 | { 123 | unsigned int bytes_read = 0; 124 | unsigned int data_size = 0; 125 | unsigned int tag = 0; 126 | unsigned int wire_type = 0; 127 | 128 | bytes_read = ReadProtoNumber(pubInput, cubAvail, &tag, 4); 129 | cubAvail -= bytes_read; 130 | wire_type = tag & 0x07; 131 | tag = tag >> 3; 132 | 133 | switch (wire_type) 134 | { 135 | case 0: // Varint - int32, int64, uint32, uint64, sint32, sint64, bool, enum 136 | data_size = ReadProtoNumber(pubInput + bytes_read, cubAvail, pubDest, cubSize ? *cubSize : 0, false); 137 | bytes_read += data_size; 138 | break; 139 | case 1: // 64-bit - fixed64, sfixed64, double 140 | if (pubDest) 141 | ReadProtoNumber(pubInput + bytes_read, cubAvail, pubDest, 8, true); 142 | data_size = 8; 143 | bytes_read += 8; 144 | break; 145 | case 5: // 32-bit - fixed32, sfixed32, float 146 | if (pubDest) 147 | ReadProtoNumber(pubInput + bytes_read, cubAvail, pubDest, 4, true); 148 | data_size = 4; 149 | bytes_read += 4; 150 | break; 151 | case 2: // Length-delimited - string, bytes, embedded messages, packed repeated fields 152 | if (cubSize) 153 | data_size = *cubSize; 154 | bytes_read += ReadProtoLengthDelimited(pubInput + bytes_read, cubAvail, pubDest, &data_size); 155 | break; 156 | default: 157 | break; 158 | } 159 | 160 | if (punTag) 161 | *punTag = tag; 162 | if (punWireType) 163 | *punWireType = wire_type; 164 | if (cubSize) 165 | *cubSize = data_size; 166 | 167 | return bytes_read; 168 | } 169 | 170 | bool GetFieldDataByTag(unsigned int nTag, const unsigned char *pubInput, unsigned int cubAvail, void *pubDest, unsigned int *cubSize, unsigned int *cubTotalRead = NULL) 171 | { 172 | unsigned int bytes_read = 0; 173 | unsigned int bytes_read_field = 0; 174 | unsigned int data_size; 175 | unsigned int tag = 0; 176 | unsigned int wire_type = 0; 177 | bool result = false; 178 | 179 | while (cubAvail > 0) 180 | { 181 | data_size = *cubSize; 182 | bytes_read_field = ReadProtoField(pubInput + bytes_read, cubAvail, &tag, &wire_type, NULL, &data_size); 183 | 184 | if ((wire_type != 0 && wire_type != 1 && wire_type != 2 && wire_type != 5) || (data_size > cubAvail)) 185 | { 186 | break; 187 | } 188 | 189 | if (tag == nTag) 190 | { 191 | bytes_read += ReadProtoField(pubInput + bytes_read, cubAvail, NULL, NULL, pubDest, cubSize); 192 | if (cubTotalRead) 193 | *cubTotalRead = bytes_read; 194 | result = true; 195 | break; 196 | } 197 | bytes_read += bytes_read_field; 198 | cubAvail -= bytes_read_field; 199 | } 200 | 201 | return result; 202 | } 203 | -------------------------------------------------------------------------------- /protoreader.h: -------------------------------------------------------------------------------- 1 | #ifndef PROTOREADER_H 2 | #define PROTOREADER_H 3 | 4 | unsigned int ReadProtoNumber(const unsigned char *pubInput, unsigned int cubAvail, void *pubDest, unsigned int cubSize, bool bFixed = false); 5 | unsigned int ReadProtoLengthDelimited(const unsigned char *pubInput, unsigned int cubAvail, void *pubDest = NULL, unsigned int *cubSize = NULL); 6 | unsigned int ReadProtoField(const unsigned char *pubInput, unsigned int cubAvail, unsigned int *punTag, unsigned int *punWireType, void *pubDest = NULL, unsigned int *cubSize = NULL); 7 | bool GetFieldDataByTag(unsigned int nTag, const unsigned char *pubInput, unsigned int cubAvail, void *pubDest, unsigned int *cubSize, unsigned int *cubTotalRead = NULL); 8 | 9 | #endif // PROTOREADER_H 10 | -------------------------------------------------------------------------------- /spprt.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Steam Parental Pin Recovery Tool 3 | * 4 | * MIT License 5 | * 6 | * Copyright (c) 2017 Nephrite 7 | */ 8 | 9 | //#define STEAMWORKS_CLIENT_INTERFACES 10 | //#define NO_CSTEAMID_STL 11 | 12 | #include "./3rdparty/OSW/OpenSteamworks/Steamworks.h" 13 | #include "IClientParentalSettings.h" 14 | #include "utlbuffer_mini.h" 15 | #include "protoreader.h" 16 | #include "CSteamAPI.h" 17 | 18 | extern "C" { 19 | //#include "3rdparty/scrypt-jane/scrypt-jane.h" // scrypt 20 | //#include "3rdparty/scrypt-jane/code/scrypt-jane-portable.h" // + 21 | //#include "3rdparty/scrypt-jane/code/scrypt-jane-hash.h" // scrypt_pbkdf2 22 | 23 | // ↑ or ↓ 24 | #include "3rdparty/scrypt-jane/scrypt-jane.c" // same shit, less size ¯\_(ツ)_/¯ 25 | } 26 | 27 | CSteamAPI SteamApi; 28 | 29 | uint32 brute_v4(uint8 *pubSalt, uint32 cubSaltSize, uint8 *pubPasswordHash, uint32 cubHashSize) 30 | { 31 | uint8 digest[32]; 32 | uint32 password; 33 | uint8 a, b, c, d; 34 | 35 | for (a = '0'; a <= '9'; a++) 36 | { 37 | for (b = '0'; b <= '9'; b++) 38 | { 39 | SteamApi.Tier0_Log("%d%% ", a * 10 + b - 528); 40 | for (c = '0'; c <= '9'; c++) 41 | { 42 | for (d = '0'; d <= '9'; d++) 43 | { 44 | password = a | (b << 8) | (c << 16) | (d << 24); 45 | scrypt_pbkdf2((uint8 *)&password, sizeof(password), pubSalt, cubSaltSize, 10000, digest, sizeof(digest)); 46 | if (memcmp(digest, pubPasswordHash, cubHashSize) == 0) 47 | { 48 | SteamApi.Tier0_Log("Done!\n"); 49 | return password; 50 | } 51 | } 52 | } 53 | } 54 | } 55 | 56 | return 0; 57 | } 58 | 59 | uint32 brute_v6(uint8 *pubSalt, uint32 cubSaltSize, uint8 *pubPasswordHash, uint32 cubHashSize) 60 | { 61 | uint8 digest[32]; 62 | uint32 password; 63 | uint8 a, b, c, d; 64 | 65 | for (a = '0'; a <= '9'; a++) 66 | { 67 | for (b = '0'; b <= '9'; b++) 68 | { 69 | SteamApi.Tier0_Log("%d%% ", a * 10 + b - 528); 70 | for (c = '0'; c <= '9'; c++) 71 | { 72 | for (d = '0'; d <= '9'; d++) 73 | { 74 | password = a | (b << 8) | (c << 16) | (d << 24); 75 | scrypt((uint8 *)&password, sizeof(password), pubSalt, cubSaltSize, 12, 3, 0, digest, sizeof(digest)); 76 | if (memcmp(digest, pubPasswordHash, cubHashSize) == 0) 77 | { 78 | SteamApi.Tier0_Log("Done!\n"); 79 | return password; 80 | } 81 | } 82 | } 83 | } 84 | } 85 | 86 | return 0; 87 | } 88 | 89 | int main() 90 | { 91 | if (!SteamApi.Load()) 92 | { 93 | // Tier0 is not available here 94 | //printf("Unable to load steamclient.\n"); 95 | return 1; 96 | } 97 | 98 | if (!SteamApi.Connect()) 99 | { 100 | SteamApi.Tier0_Msg("Unable to connect to Steam or get the client engine interfaces.\n"); 101 | return 2; 102 | } 103 | 104 | SteamApi.Tier0_Msg("Connected to Steam Client\n\n"); 105 | 106 | if (!SteamApi.User->BLoggedOn()) 107 | { 108 | SteamApi.Tier0_Msg("Not logged on.\n"); 109 | return 2; 110 | } 111 | 112 | SteamApi.Tier0_Msg("Persona name: %s\n", SteamApi.Friends->GetPersonaName()); 113 | SteamApi.Tier0_Msg("SteamID: %llu\n\n", SteamApi.User->GetSteamID().ConvertToUint64()); 114 | 115 | char response; 116 | while (true) 117 | { 118 | SteamApi.Tier0_Msg("Is this your account? (y/n): "); 119 | response = getchar(); 120 | fflush(stdin); 121 | if (response == 'Y' || response == 'y') 122 | break; 123 | if (response == 'N' || response == 'n') 124 | { 125 | SteamApi.Tier0_Msg("Okay, h4x0r... "); 126 | Sleep(1000); 127 | SteamApi.Tier0_Msg("Reported!"); 128 | Sleep(3000); 129 | SteamApi.Tier0_Msg("\nJust kidding :D\n"); 130 | return 0; 131 | } 132 | SteamApi.Tier0_Msg("Please type 'Y' or 'N'\n"); 133 | } 134 | 135 | uint32 i = 0; 136 | CUtlBuffer MsgParentalSettings(0, 0); 137 | 138 | SteamApi.Tier0_Msg("Trying to get Parental Settings...\n"); 139 | 140 | uint64 hHandle = SteamApi.UnifiedMessages->SendMethod("Parental.GetSignedParentalSettings#1", NULL, 0, 0); 141 | 142 | if (hHandle == 0) 143 | { 144 | SteamApi.Tier0_Msg("Cannot send Unified Message: handle == 0\n"); 145 | return 3; 146 | } 147 | 148 | uint32 unResponseSize = 0; 149 | EResult eResult = k_EResultFail; 150 | bool res; 151 | 152 | do 153 | { 154 | Sleep(200); 155 | res = SteamApi.UnifiedMessages->GetMethodResponseInfo(hHandle, &unResponseSize, &eResult); 156 | i += 1; 157 | } 158 | while (!res && (i < 5)); 159 | 160 | if (eResult != k_EResultOK) 161 | { 162 | SteamApi.Tier0_Msg("Error: response is not available, result = %u\n", eResult); 163 | SteamApi.UnifiedMessages->ReleaseMethod(hHandle); 164 | return 4; 165 | } 166 | 167 | SteamApi.Tier0_Msg("OK: response size = %u\n", unResponseSize); 168 | MsgParentalSettings.EnsureCapacity(unResponseSize); 169 | res = SteamApi.UnifiedMessages->GetMethodResponseData(hHandle, MsgParentalSettings.Base(), unResponseSize, true); 170 | if (!res) 171 | { 172 | SteamApi.Tier0_Msg("Error: no data available\n"); 173 | return 5; 174 | } 175 | 176 | uint8 passwordhashtype = 0; 177 | uint8 salt[8] = {0}; 178 | uint8 passwordhash[32] = {0}; 179 | bool is_enabled = false; 180 | 181 | uint8 *msg_ptr = MsgParentalSettings.Base(); 182 | uint32 msg_size = MsgParentalSettings.Size(); 183 | 184 | // extract inner proto-message 185 | if (!GetFieldDataByTag(1, msg_ptr, msg_size, msg_ptr, &msg_size)) 186 | { 187 | SteamApi.Tier0_Msg("Awww.. Why am I failing every fockin time??\n"); 188 | return 6; 189 | } 190 | 191 | #ifdef DEBUG 192 | SteamApi.Tier0_Log("[DEBUG] MsgSettings: %u ", msg_size); 193 | for (i = 0; i < msg_size; ++i) 194 | SteamApi.Tier0_Log("%02X", msg_ptr[i]); 195 | SteamApi.Tier0_Log("\n"); 196 | #endif 197 | 198 | uint32 size = sizeof(is_enabled); 199 | if (!GetFieldDataByTag(9, msg_ptr, msg_size, &is_enabled, &size)) 200 | { 201 | SteamApi.Tier0_Warning("enabled - fail\n"); 202 | } 203 | 204 | if (!is_enabled) // IClientUser->BIsParentalLockEnabled() 205 | { 206 | SteamApi.Tier0_Msg("Parental lock is not enabled\n"); 207 | return 0; 208 | } 209 | 210 | CUtlBuffer SerializedParentalSettings(0, 0); 211 | uint32 value = 0; 212 | uint8 *serial_ptr; 213 | 214 | if (SteamApi.ParentalSettings) 215 | { 216 | if (SteamApi.ParentalSettings->BGetSerializedParentalSettings(&SerializedParentalSettings)) 217 | { 218 | serial_ptr = SerializedParentalSettings.Base(); 219 | 220 | #ifdef DEBUG 221 | value = SerializedParentalSettings.Size(); 222 | SteamApi.Tier0_Log("[DEBUG] Serialized Settings: %d ", value); 223 | for (i = 0; i < value; ++i) 224 | { 225 | SteamApi.Tier0_Log("%02X", serial_ptr[i]); 226 | } 227 | SteamApi.Tier0_Log("\n"); 228 | #endif 229 | 230 | value = *(uint32 *)serial_ptr; 231 | #ifdef DEBUG 232 | SteamApi.Tier0_Msg("state: %d (%s)\n", value, (value == 1 ? "Locked" : (value == 2) ? "Unlocked" : "Unknown")); 233 | #endif 234 | } 235 | else 236 | { 237 | SteamApi.Tier0_Msg("Error: cannot get serialized Parental Settings\n"); 238 | value = 1; 239 | } 240 | } 241 | 242 | if (value == 1 || !SteamApi.ParentalSettings) // IClientUser->BIsParentalLockLocked() 243 | { 244 | size = sizeof(passwordhashtype); 245 | if (GetFieldDataByTag(6, msg_ptr, msg_size, &passwordhashtype, &size)) 246 | SteamApi.Tier0_Msg("hash type: %u\n", passwordhashtype); 247 | else 248 | SteamApi.Tier0_Warning("hash type - fail\n"); 249 | 250 | size = sizeof(salt); 251 | if (GetFieldDataByTag(7, msg_ptr, msg_size, salt, &size)) 252 | { 253 | SteamApi.Tier0_Msg("salt: "); 254 | for (i = 0; i < sizeof(salt); ++i) 255 | SteamApi.Tier0_Msg("%02X", salt[i]); 256 | SteamApi.Tier0_Msg("\n"); 257 | } 258 | else 259 | SteamApi.Tier0_Warning("salt - fail\n"); 260 | 261 | size = sizeof(passwordhash); 262 | if (GetFieldDataByTag(8, msg_ptr, msg_size, passwordhash, &size)) 263 | { 264 | SteamApi.Tier0_Msg("hash: "); 265 | for (i = 0; i < sizeof(passwordhash); ++i) 266 | SteamApi.Tier0_Msg("%02X", passwordhash[i]); 267 | SteamApi.Tier0_Msg("\n"); 268 | } 269 | else 270 | SteamApi.Tier0_Warning("hash - fail\n"); 271 | 272 | uint32 pin; 273 | uint64 tick_start, tick_stop; 274 | 275 | SteamApi.Tier0_Msg("Bruteforcing...\n"); 276 | tick_start = SteamApi.Tier0_Plat_RelativeTicks(); 277 | 278 | switch (passwordhashtype) 279 | { 280 | case 4: 281 | pin = brute_v4(salt, sizeof(salt), passwordhash, sizeof(passwordhash)); 282 | break; 283 | case 6: 284 | pin = brute_v6(salt, sizeof(salt), passwordhash, sizeof(passwordhash)); 285 | break; 286 | default: 287 | SteamApi.Tier0_Warning("Unsupported hash type (%u)\n", passwordhashtype); 288 | return -1; 289 | } 290 | 291 | tick_stop = SteamApi.Tier0_Plat_RelativeTicks(); 292 | SteamApi.Tier0_Msg("Total time taken by CPU: %.2fs\n", (float)SteamApi.Tier0_Plat_TickDiffMilliSec(tick_start, tick_stop) / 1000.0f); 293 | 294 | if (pin != 0) 295 | { 296 | SteamApi.Tier0_Msg("Pin: \"%c%c%c%c\"\n", pin, pin >> 8, pin >> 16, pin >> 24); 297 | SteamApi.Tier0_Msg("Use it to unlock your Steam Client\n"); 298 | } 299 | else 300 | SteamApi.Tier0_Msg("Pin not found\n"); 301 | } 302 | else 303 | { 304 | SteamApi.Tier0_Msg("Parental lock is not locked\n"); 305 | 306 | // pin is saved, parse the settings 307 | serial_ptr += 4; 308 | //value = *(uint32 *)serial_ptr; 309 | //printf("applist_base_id: %s (%d)\n", (value == 1 ? "Block all games" : "Allow all games"), value); 310 | serial_ptr += 4; 311 | value = *(uint32 *)serial_ptr; 312 | //printf("applist_base length: %d (skip)\n", value); 313 | serial_ptr += 4; 314 | for (i = 0; i < value; ++i) 315 | { 316 | serial_ptr += 8; 317 | } 318 | value = *(uint32 *)serial_ptr; 319 | //printf("applist_custom length: %d\n", value); 320 | serial_ptr += 4; 321 | for (i = 0; i < value; ++i) 322 | { 323 | //printf("> appid: %d, allowed: %d\n", *(uint32 *)serial_ptr, *(uint32 *)(serial_ptr + 4)); 324 | serial_ptr += 8; 325 | } 326 | //value = *(uint32 *)serial_ptr; 327 | //printf("enabled_features: %d (0x%X)\n", value, value); 328 | serial_ptr += 4; 329 | value = *(uint32 *)serial_ptr; 330 | serial_ptr += 4; 331 | //printf("recovery_email: \"%s\" (length = %d)\n", serial_ptr, value); 332 | serial_ptr += value + 1; // length + \0 ?? 333 | value = *(uint32 *)serial_ptr; 334 | serial_ptr += 4; 335 | SteamApi.Tier0_Msg("Pin: \""); 336 | for (i = 0; i < value; ++i) 337 | { 338 | SteamApi.Tier0_Msg("%c", serial_ptr[i]); 339 | } 340 | SteamApi.Tier0_Msg("\"\n"); 341 | } 342 | 343 | SteamApi.Tier0_Msg("Press to exit..."); 344 | getchar(); 345 | 346 | return 0; 347 | } 348 | -------------------------------------------------------------------------------- /utlbuffer_mini.h: -------------------------------------------------------------------------------- 1 | #ifndef UTLBUFFER_MINI_H 2 | #define UTLBUFFER_MINI_H 3 | 4 | #ifdef _WIN32 5 | #pragma once 6 | #endif 7 | 8 | class CUtlBuffer 9 | { 10 | public: 11 | typedef bool (CUtlBuffer::*OverflowFunc_t)(int nSize); 12 | 13 | CUtlBuffer(int growSize = 0, int initSize = 0) 14 | : m_pMemory(nullptr), m_nAllocationCount(0), m_nGrowSize(growSize) 15 | { 16 | EnsureCapacity(initSize); 17 | m_GetOverflowFunc = &EnsureCapacity; 18 | m_PutOverflowFunc = &EnsureCapacity; 19 | m_dummy1 = m_dummy2 = m_dummy3 = m_dummy4 = m_dummy5 = m_dummy6 = m_Byteswap = 0; 20 | } 21 | 22 | ~CUtlBuffer() 23 | { 24 | Purge(); 25 | } 26 | 27 | unsigned char *Base() 28 | { 29 | return m_pMemory; 30 | } 31 | 32 | int Size() 33 | { 34 | return m_nAllocationCount; 35 | } 36 | 37 | bool EnsureCapacity(int num) 38 | { 39 | if (m_nAllocationCount >= num) 40 | return true; 41 | 42 | if (m_nGrowSize < 0) 43 | return false; 44 | 45 | m_nAllocationCount = num; 46 | 47 | if (m_pMemory) 48 | { 49 | m_pMemory = (unsigned char *)realloc(m_pMemory, m_nAllocationCount * sizeof(unsigned char)); 50 | } 51 | else 52 | { 53 | m_pMemory = (unsigned char *)malloc(m_nAllocationCount * sizeof(unsigned char)); 54 | } 55 | return true; 56 | } 57 | 58 | void Purge() 59 | { 60 | if (m_nGrowSize >= 0) 61 | { 62 | if (m_pMemory) 63 | { 64 | free(m_pMemory); 65 | m_pMemory = nullptr; 66 | } 67 | m_nAllocationCount = 0; 68 | } 69 | m_dummy1 = m_dummy2 = m_dummy3 = m_dummy4 = m_dummy5 = m_dummy6 = m_Byteswap = 0; 70 | } 71 | 72 | private: 73 | int m_dummy1; 74 | unsigned char *m_pMemory; 75 | int m_nAllocationCount; 76 | int m_nGrowSize; 77 | 78 | int m_dummy2; // 2 79 | int m_dummy3; // dummy 80 | int m_dummy4; // 4 81 | int m_dummy5; // me 82 | int m_dummy6; // ¯\_(ツ)_/¯ 83 | 84 | OverflowFunc_t m_GetOverflowFunc; 85 | OverflowFunc_t m_PutOverflowFunc; 86 | 87 | int m_Byteswap; 88 | }; 89 | 90 | #endif // UTLBUFFER_MINI_H 91 | --------------------------------------------------------------------------------