kansasdude
Well-Known Member
- Sep 13, 2017
- 1,552
- 1,237
- 376
0.6 will have a quest log which should helpIs there a walkthrough for this game? I cant get some scenes to trigger.
And I'm a patreon
0.6 will have a quest log which should helpIs there a walkthrough for this game? I cant get some scenes to trigger.
And I'm a patreon
Here is one with English and Russian versions.Is there a walkthrough for this game? I cant get some scenes to trigger.
And I'm a patreon
If you've downloaded the client and let it update, you should already have all of the images (they are downloaded before authenticating through Patreon). Those files should be available at `%LOCALAPPDATA%Low\Sandlust Games Ltd\Glamour\images` as PNGs with no file suffix.Is it just me or is it a slow download?? if it is i can give you a faster one![]()
There were more places that you have to change than just that one place in the code. You have to load the dependency UnityEngine.CoreModule.dllMy first approach is modifying the PlayerPrefs.SetInt("pledge", this.pledge); statement with PlayerPrefs.SetInt("pledge", 1);, but the compiler complaints about "PlayerPrefs" name not existing. I'm not sure what to do, even tried installing Unity with VisualStudio2017, but it stays the same.
Did I make a post talking about the registry? I thought I did but I guess not. The registry keys get reset every time you start the game, and you can't change them after the game starts. Also setting the Glamour registry keys to read only will cause the game to throw an exception and be stuck loading at the menu. You just have to change the code that sets the keys.When that failed, I tried modifying the registry, so the PlayerPrefs settings should get another values, but somehow it doesn't work for now. Any clue where to check any of my leads? Am I lost (probably...).
I don't think I saw any posts you made, I just saw others that posted saying they looked into the Assembly dll and they just assumed that was the only code stored client side which was wrong. I don't really know much about networking though and how to intercept packets. Would reading the actual contents of the requests/responses/JSON files be easy?I actually said that the part you download is effectively just a glorified web browser, which is why I never bothered digging into scripts.dll. I observed the game state loop going out over HTTP and recognized that event, display and dialogue decisions were being made remotely (and passed via JSON to the client).
I wasn't being specific when I said that. =P It's just that I read the first couple pages of this thread and saw people saying that the game would never be cracked and was impossible to modify because of the online stuff but it's not really any different than every other Unity game so idk why people were saying that.Clearly I don't know anything. With that out of the way, how has your investigation gone in seeing if your modifications were successful at unlocking the latest version?
Game events newer than two months will be available in the game. I don't know anything, but I suspect those would be working at the hotel, and something to do with a café. I have no idea how to trigger those events.
i was talking about the cg`s Mega link, it was like 2 mb/s download for me and i think my link is fasterIf you've downloaded the client and let it update, you should already have all of the images (they are downloaded before authenticating through Patreon). Those files should be available at `%LOCALAPPDATA%Low\Sandlust Games Ltd\Glamour\images` as PNGs with no file suffix.
DS took no effort in protecting the content of the messages (no encryption or obfuscation, it's just JSON over HTTP). I have about 75% of the notes required to draw up a protocol sequence diagram to document the interactions between client and server, but stopped working on that after perceiving little interest or benefit in doing so. Based on your interest, I'll try to finish that this week some time.I don't really know much about networking though and how to intercept packets. Would reading the actual contents of the requests/responses/JSON files be easy?
As far as a running program goes I'm sure it's like the vast majority of other Unity games out there. The difference is in where game state is kept and game decisions are made. Specifically, it appears that the game client connects to a server to which it passes instructions about user actions while the server responds with game state updates.it's not really any different than every other Unity game so idk why people were saying that.
That's basically where I ended up as well.And lol, I still haven't confirmed if I actually have the new content or if the game only says I do.. I don't really want to play the game for 2 hours just to find out. xP
Back in the day I usedI don't really know much about networking though and how to intercept packets. Would reading the actual contents of the requests/responses/JSON files be easy?
I actually worked on the network side as well (as I am more used to it than reversing/compiling), and noticed that everytime the game launches, it sends the client ID to the game server, which then replies with the account information (version, pledge, patreon) that is dumped in the registry. I've modified that information client-side, so the game thinks that the pledge is made, but, as @NachoCheese say, all of the processing is done server-side, so the events associated with patreon accounts won't happen.There were more places that you have to change than just that one place in the code. You have to load the dependency UnityEngine.CoreModule.dll
Did I make a post talking about the registry? I thought I did but I guess not. The registry keys get reset every time you start the game, and you can't change them after the game starts. Also setting the Glamour registry keys to read only will cause the game to throw an exception and be stuck loading at the menu. You just have to change the code that sets the keys.
I made a python script to intercept the requests, print them out, and change some server replies so the client get the values I want, but the only meaningful thing sent to the server is the client ID (as far as I know), and it is a long, hash-type string, hard to bruteforce (and doing so would mess with other people's saved games).I don't think I saw any posts you made, I just saw others that posted saying they looked into the Assembly dll and they just assumed that was the only code stored client side which was wrong. I don't really know much about networking though and how to intercept packets. Would reading the actual contents of the requests/responses/JSON files be easy?
Actually, it would be useful to get one or two active client ID's, maybe via private message, and keeping in mind that it could alter the saved games (there isn't much to play, though, so...). I've already tried some values, and for the time being I would keep "6" as value, it has given me the full patreon access screen:If one of you is a patreon who is certain they have the patreon exclusive content, if you want to help could you do this please:
1. Type and open 'regedit' in windows search
2. Copy and paste this in the top search bar: Computer\HKEY_CURRENT_USER\Software\Sandlust Games Ltd\Glamour
3. Tell me what the numbers you have in these two parentheses are
View attachment 142192
Appreciate it!Here is one with English and Russian versions.
Yeah I saw that the account info is stored in the registry and I assumed the game used those keys to check if it should send the patreon exclusive content but found out that wasn't the case and I think it only uses the registry values for the menu screen.I actually worked on the network side as well (as I am more used to it than reversing/compiling), and noticed that everytime the game launches, it sends the client ID to the game server, which then replies with the account information (version, pledge, patreon) that is dumped in the registry. I've modified that information client-side, so the game thinks that the pledge is made, but, as @NachoCheese say, all of the processing is done server-side, so the events associated with patreon accounts won't happen.
I made a python script to intercept the requests, print them out, and change some server replies so the client get the values I want, but the only meaningful thing sent to the server is the client ID (as far as I know), and it is a long, hash-type string, hard to bruteforce (and doing so would mess with other people's saved games).
If you want the script, I can send it to you, is not complicated to set it up, and would allow you to see the traffic in real time (actually, is work in progress, but works well as it is, it's just not pretty).
Actually, it would be useful to get one or two active client ID's, maybe via private message, and keeping in mind that it could alter the saved games (there isn't much to play, though, so...). I've already tried some values, and for the time being I would keep "6" as value, it has given me the full patreon access screen
So you receive a setback?and I thought changing this to always set pledge to 40 would unlock the patreon content but no luck.
Assembly assembly = Assembly.LoadFrom(Application.persistentDataPath + "/lain.dll");
public static LoginResponse Parse(string source)
{
source = source.Replace("\"pledge\":0", "\"pledge\":40");
Debug.Log("source: " + source);
return JsonConvert.DeserializeObject<LoginResponse>(source);
}
public void UpdatePlayerPrefs()
{
PlayerPrefs.SetInt("patron", 1);
PlayerPrefs.SetInt("pledge", 40);
}
public static IEnumerator SendStatusRequest(string id)
{
WWWForm wwwform = new WWWForm();
wwwform.AddField("id", id);
WWW request = new WWW(PlayerPrefs.GetString("ServerUrl") + "/api/status", wwwform);
yield return request;
JObject jobject = JObject.Parse(request.text);
PlayerPrefs.SetInt("patron", 1);
PlayerPrefs.SetInt("pledge", 40);
PlayerPrefs.SetInt("version", jobject["version"].ToObject<int>());
yield break;
}
I set 6 as the pledge value, as 40 froze my game, so I tried adding one per level, and 6 gave me "the most", but it could be wrong.Yeah I saw that the account info is stored in the registry and I assumed the game used those keys to check if it should send the patreon exclusive content but found out that wasn't the case and I think it only uses the registry values for the menu screen.
I also figured out how to run the game with the .Net debugger so I can read requests/responses using the locales window. Indeed the server still knows what pateron tier a user is without checking the registry and I thought changing this to always set pledge to 40 would unlock the patreon content but no luck.
And is 6 the value you're using for the game version? I was hoping that patron's just had a different version # for the patreon content but I think it's still set to version 5 for them as well.Code:public static LoginResponse Parse(string source) { source = source.Replace("\"pledge\":0", "\"pledge\":40"); Debug.Log("source: " + source); return JsonConvert.DeserializeObject<LoginResponse>(source); }
Ah, well 40 definitely works but those values are only used for displaying when you get updates on the main menu I think so I don't think it really matters what it is set to. If you want it set to 40 though you can download my files in the post above.I set 6 as the pledge value, as 40 froze my game, so I tried adding one per level, and 6 gave me "the most", but it could be wrong.
I still do.Back in the day I usedYou must be registered to see the links.
I'd be careful about using those. If I were as paranoid about piracy as DS apparently is, I'd have something in place to automatically blacklist Patreons whos' IDs appear to be logged in from two or more places at once.Actually, it would be useful to get one or two active client ID's, maybe via private message, and keeping in mind that it could alter the saved games (there isn't much to play, though, so...). I've already tried some values, and for the time being I would keep "6" as value, it has given me the full patreon access screen:
{
"scripts.dll": "27b58bc01180293c88f72855c96616e8",
"content": "b2e176d524e644cf511b415468b2df35",
"scenes": "84dd8df8994c2b44c935b149ea76dd5a"
}
{
...
"wardrobe/casual-3-big":1220652,
"wardrobe/casual-3":22633,
"wardrobe/evening-1-big":1019972,
"wardrobe/evening-1":13460,
"wardrobe/evening-2-big":1052070,
...
}
I think that the UUID is decided/created by the client. So I think it should be possible to set a custom ID but I'm not really sure if that's useful for anything, I doubt it is.After all resources have been loaded, client issues a POST request for /api/status with the following keys:
The API responds with a JSON object with the following keys:
- id: a UUID. I'm assuming this is used to look up the user's information through the Patreon API.
- patron: 0 (Assuming boolean: if this user is a Patron or not)
- pledge: 0 (Assuming pledge value)
- version: 5 (Assuming minor version of the client)
I'm not sure where in the code the logic is for the first response in the quote above. I think it's related to the LoginResponse class -> Parse() method but I don't remember. If it is then I changed the patron and pledge amount as soon as the client received the response so the patron and pledge part aren't important.The API responds with a JSON object with the following keys:
The client issues a POST request for /api/start with the following keys:
- status: ok
- token: (a 164 byte string that appears to have several Base64 encoded segments separated by the '.' character)
- Segment 1: a 36 byte Base64 encoded JSON object with the following keys:
- alg: HS256
- typ: JWT
- Note:
You must be registered to see the links- Segment 2: an 83 byte Base64 encoded JSON object with the following keys:
- id: The previously seen UUID
- iat: The number of seconds since the UNIX epoch.
- Segment 3: a 43 byte string that appears to be random data. (this base64 decodes to 32 bytes, so this is quite likely)
- saves: an array (empty)
- patron: false (if the user is a patron or not)
- pledge: 0 (the pledge level of the patron)
When the user clicks on anything, the client issues a POST request for /api/update with the following keys:
- token: the previously seen token
The API responds with a JSON object with the same keys as seen above (to start)
- token: previously seen token
Oh, a little of this. A little of that.Nice work! Is your job related to networking or IT by any chance?
With that packet capture, the first time that a UUID passed across the network was from client to server, but I wanted to reset the VM I was testing with and check it's behavior from the start. (Maybe UUID is set upon initial connection and passed client to server as a way of identifying a unique client).I think that the UUID is decided/created by the client. So I think it should be possible to set a custom ID but I'm not really sure if that's useful for anything, I doubt it is.
My guess was that the information is just displayed locally.The JSON "patreon, pledge, version" response is done by the NetworkHelper class -> SendStatusRequest(string id) method. Once the values are received the values are set in the registry and not used for anything else. So I'm 99% sure these values aren't related to deciding what content the user has unlocked.
Most likely. I was surprised that the UUID was actually encoded into the token string. Digging into the patreon login process might shed more light on why this is handled this way. That's something I skipped deep diving into at the time as I was more interested in api/start and api/update calls when I captured these packets.I'm not sure where in the code the logic is for the first response in the quote above. I think it's related to the LoginResponse class -> Parse() method but I don't remember. If it is then I changed the patron and pledge amount as soon as the client received the response so the patron and pledge part aren't important.
HTTP is inherently stateless, the tokens are definitely being used by the clients to uniquely identify themselves to the server. This would be a requirement if game state is maintained on the server, as the server would need to know *which* game instance performed a given action (which is further supported by the content of the messages being passed, the client is always just telling the server which action was performed, and all of the state data is coming down from the server each time an action is performed)So what are tokens used for? In the scripts.dll there is code for handling and I think creating tokens too, but it wasn't very clear what they were being used for.
As far as I can tell, saving on the server is likely just marking a game state as more persistent than every other game state it keeps track of. While it could keep that data in memory within the node.js process, it's probably a much better idea if it's pushing that state all the way back to a persistent database and then just updating as it goes. That would also mean that DS can restart the server without screwing over everyone who's currently playing. As for how saves are specifically triggered server-side, I never dug into that.Also if the user id is tied to a patreon account, you probably could change the code in the client to save to your personal patreon account user id but use a patron's user id to access the api. Not sure if multiple people using the same user id to access the api would screw with each other's games or not though.