Jump to content

HotelStory not complying


GeraldLim
 Share

Recommended Posts

I've seen a few threads about this game but none were resolved so imma try again. 

I'm trying to get more gems or builders, and I've tried a few different methods but none so far hahe worked. Game is offline and I did all the testing with no Internet connection.

 

I've tried finding the value directly, and I either get a value I can't change (changes back) or I find no value at all. I've tried a fuzzy search for Dwords and found 2 values that change once my gem count changes, but I can't seem to find a correlation between the values. (Used one gem, difference between the values is 501. Another gem, 492. Another gem, 494.) If I change those 2 values, the game sets my gems and coins to 0, and no matter what I do in game the values are stuck at 0. Is this game unhackable?

I thought the security would be loose since its technically abandonware, but guess I was wrong.

Link to comment
Share on other sites

Apk of the game has 4 sets of libraries for different ABIs: armeabi-v7a, arm64-v8a, x86, x86_64. In my case 32-bit android emulator for Windows was used causing game libraries for x86 to be used. Correspondingly, all library-specific values like offsets that will be shown or mentioned in this post are only applicable to game's library for x86.

Values of interest (coins, diamonds, max workers) are located in bss section of libnative-lib.so library. They can't be edited directly because game computes sha-256 hashes of several blocks of memory with important values and checks validity of stored hashes during every operation that includes reading or writing protected values.

So in order to be able to directly edit values of interest in process memory verification of hashes needs to be disabled first. With GG it can be done by editing instructions in code segment of the library in process memory. The function that needs to be modified in library is named "IsMatchHash". It is located at offset 0x16E480 from library start. There are at least several different modifications of function's instructions to achieve desired result of function always returning 1 (true). One of the options is to modify 2 subsequent instructions at offsets 0x16E507 and 0x16E50A (see illustration below) to MOV AL, 0x1 (B0 01), MOV BYTE PTR [EDI + 0x29] (C6 47 29 01) and NOP (90) to edit all 7 bytes of original instructions.
image.thumb.png.02b71e4990633d995b0fa5e4bbcc1465.png

To find values of interest in process memory, besides using offsets to them from library start that can be discovered by analysis of library with the help of disassemblers, GG search capabilities can be used. Memory ranges with bss sections of application libraries in GG in most cases are classified as "Cb: C++ .bss". This can be used to find values of interest faster and more accurately by selecting only "Cb" type in list of memory ranges types. Having that done, there is one simple approach to find values of interest by searching for nearby value - player name string. For example, if player name is "TestPlayer123", in GG it can be searched with search string ":TestPlayer123". Colon as first character of search string means to search for specified UTF-8 encoded string. One occurrence of player name string is expected to be found. Values of interest are located within several hundred bytes from first byte of the string.

After finding values of interest, adding them to saved list and assigning corresponding names to them, saved list looks like this: 
image.thumb.png.a453134dd914ab8b48dbbc5113a36925.png

Maximal amount of workers is plain dword value that can be simply edited to desired one. Coins and diamonds are each stored as two separate dword values that give real value when they are XOR'ed (value1 XOR value2 = real_value). Either first or second value can be edited to 0 and the remaining value can then be edited to desired one. This works because value XOR 0 = value.

Finally, here is an illustration of the result of modifying values of interest:
image.thumb.png.264bb91486a3ddb25cba7510b8c709d0.png

Link to comment
Share on other sites

1 hour ago, CmP said:

Apk of the game has 4 sets of libraries for different ABIs: armeabi-v7a, arm64-v8a, x86, x86_64. In my case 32-bit android emulator for Windows was used causing game libraries for x86 to be used. Correspondingly, all library-specific values like offsets that will be shown or mentioned in this post are only applicable to game's library for x86.

Values of interest (coins, diamonds, max workers) are located in bss section of libnative-lib.so library. They can't be edited directly because game computes sha-256 hashes of several blocks of memory with important values and checks validity of stored hashes during every operation that includes reading or writing protected values.

So in order to be able to directly edit values of interest in process memory verification of hashes needs to be disabled first. With GG it can be done by editing instructions in code segment of the library in process memory. The function that needs to be modified in library is named "IsMatchHash". It is located at offset 0x16E480 from library start. There are at least several different modifications of function's instructions to achieve desired result of function always returning 1 (true). One of the options is to modify 2 subsequent instructions at offsets 0x16E507 and 0x16E50A (see illustration below) to MOV AL, 0x1 (B0 01), MOV BYTE PTR [EDI + 0x29] (C6 47 29 01) and NOP (90) to edit all 7 bytes of original instructions.
image.thumb.png.02b71e4990633d995b0fa5e4bbcc1465.png

To find values of interest in process memory, besides using offsets to them from library start that can be discovered by analysis of library with the help of disassemblers, GG search capabilities can be used. Memory ranges with bss sections of application libraries in GG in most cases are classified as "Cb: C++ .bss". This can be used to find values of interest faster and more accurately by selecting only "Cb" type in list of memory ranges types. Having that done, there is one simple approach to find values of interest by searching for nearby value - player name string. For example, if player name is "TestPlayer123", in GG it can be searched with search string ":TestPlayer123". Colon as first character of search string means to search for specified UTF-8 encoded string. One occurrence of player name string is expected to be found. Values of interest are located within several hundred bytes from first byte of the string.

After finding values of interest, adding them to saved list and assigning corresponding names to them, saved list looks like this: 
image.thumb.png.a453134dd914ab8b48dbbc5113a36925.png

Maximal amount of workers is plain dword value that can be simply edited to desired one. Coins and diamonds are each stored as two separate dword values that give real value when they are XOR'ed (value1 XOR value2 = real_value). Either first or second value can be edited to 0 and the remaining value can then be edited to desired one. This works because value XOR 0 = value.

Finally, here is an illustration of the result of modifying values of interest:
image.thumb.png.264bb91486a3ddb25cba7510b8c709d0.png

Holy crap this is quite detailed, thanks! 

I'm afraid since I'm new to the scene I only understand around half of what was explained here, imma see if I can poke around using the info from here and try to understand it. Thanks again!

Link to comment
Share on other sites

19 hours ago, CmP said:

Apk of the game has 4 sets of libraries for different ABIs: armeabi-v7a, arm64-v8a, x86, x86_64. In my case 32-bit android emulator for Windows was used causing game libraries for x86 to be used. Correspondingly, all library-specific values like offsets that will be shown or mentioned in this post are only applicable to game's library for x86.

Values of interest (coins, diamonds, max workers) are located in bss section of libnative-lib.so library. They can't be edited directly because game computes sha-256 hashes of several blocks of memory with important values and checks validity of stored hashes during every operation that includes reading or writing protected values.

So in order to be able to directly edit values of interest in process memory verification of hashes needs to be disabled first. With GG it can be done by editing instructions in code segment of the library in process memory. The function that needs to be modified in library is named "IsMatchHash". It is located at offset 0x16E480 from library start. There are at least several different modifications of function's instructions to achieve desired result of function always returning 1 (true). One of the options is to modify 2 subsequent instructions at offsets 0x16E507 and 0x16E50A (see illustration below) to MOV AL, 0x1 (B0 01), MOV BYTE PTR [EDI + 0x29] (C6 47 29 01) and NOP (90) to edit all 7 bytes of original instructions.
image.thumb.png.02b71e4990633d995b0fa5e4bbcc1465.png

To find values of interest in process memory, besides using offsets to them from library start that can be discovered by analysis of library with the help of disassemblers, GG search capabilities can be used. Memory ranges with bss sections of application libraries in GG in most cases are classified as "Cb: C++ .bss". This can be used to find values of interest faster and more accurately by selecting only "Cb" type in list of memory ranges types. Having that done, there is one simple approach to find values of interest by searching for nearby value - player name string. For example, if player name is "TestPlayer123", in GG it can be searched with search string ":TestPlayer123". Colon as first character of search string means to search for specified UTF-8 encoded string. One occurrence of player name string is expected to be found. Values of interest are located within several hundred bytes from first byte of the string.

After finding values of interest, adding them to saved list and assigning corresponding names to them, saved list looks like this: 
image.thumb.png.a453134dd914ab8b48dbbc5113a36925.png

Maximal amount of workers is plain dword value that can be simply edited to desired one. Coins and diamonds are each stored as two separate dword values that give real value when they are XOR'ed (value1 XOR value2 = real_value). Either first or second value can be edited to 0 and the remaining value can then be edited to desired one. This works because value XOR 0 = value.

Finally, here is an illustration of the result of modifying values of interest:
image.thumb.png.264bb91486a3ddb25cba7510b8c709d0.png

I think I understand what you're doing, but now I have no idea how to modify theassembly code. My memory viewer is all 00000000h. How do i find the start of the library?

Link to comment
Share on other sites

On 8/17/2021 at 1:34 AM, GeraldLim said:

How do i find the start of the library?

In memory editor's toolbar choose "Goto" option, then click on "Xa" button and locate entry with library name. Starting address will be specified there. Clicking on the entry will put the address in the input field. From there it can be copied and/or navigated to.

Link to comment
Share on other sites

11 hours ago, CmP said:

In memory editor's toolbar choose "Goto" option, then click on "Xa" button and locate entry with library name. Starting address will be specified there. Clicking on the entry will put the address in the input field. From there it can be copied and/or navigated to.

Alright, I was able to navigate to the section in memory, and I see the hex op codes, but I'm not sure how to edit them as hex. GG only displays them in batches of 4, so I have to edit the last hex set of the address... 704, and then edit the next batch of 708. When I try to edit the value I can only edit in decimal, how do I edit as hex?

Also sorry for the slow responses, my posts have to get approved beforehand

 

Edit: I set the view to byte so I can see the hex values for each address, but I still have to edit in decimal. I can use a converter so that shouldn't be an issue. Now I'm having the problem that no matter what I try (pausing process, freezing value) the value won't change or gets changed back. What do I do to change the instructions?

Edited by GeraldLim
Link to comment
Share on other sites

1 hour ago, GeraldLim said:

I set the view to byte so I can see the hex values for each address, but I still have to edit in decimal.

It's not necessary to convert values from decimal to hex or from hex to decimal, because GG understands both formats. Consider an example that you need to edit value of byte type to 0x88. Instead of converting 0x88 to decimal and using the result to edit the value, you can just edit the value right away by adding "h" suffix to hex value. So to edit the value you need to input "88h".

1 hour ago, GeraldLim said:

Now I'm having the problem that no matter what I try (pausing process, freezing value) the value won't change or gets changed back.

Which device or emulator do you use to run the game and GG? Which version of android is used there? Is device/emulator rooted or a virtual space application is used?

Link to comment
Share on other sites

7 hours ago, CmP said:

It's not necessary to convert values from decimal to hex or from hex to decimal, because GG understands both formats. Consider an example that you need to edit value of byte type to 0x88. Instead of converting 0x88 to decimal and using the result to edit the value, you can just edit the value right away by adding "h" suffix to hex value. So to edit the value you need to input "88h".

Didn't know that, that's quite useful, thanks

 

7 hours ago, CmP said:

Which device or emulator do you use to run the game and GG? Which version of android is used there? Is device/emulator rooted or a virtual space application is used?

Original hardware. Rooted Android 11. Note 10 plus.

Link to comment
Share on other sites

On 8/19/2021 at 1:17 PM, GeraldLim said:

Original hardware. Rooted Android 11. Note 10 plus.

Rooted devices usually don't have such limitation of not being able to modify values in memory ranges with application's code (or maybe in any memory range that doesn't have "w" permission). Possibly that it is somehow related with security improvements in android 11, but this is just a guess.

Link to comment
Share on other sites

On 8/21/2021 at 6:55 AM, CmP said:

Rooted devices usually don't have such limitation of not being able to modify values in memory ranges with application's code (or maybe in any memory range that doesn't have "w" permission). Possibly that it is somehow related with security improvements in android 11, but this is just a guess.

So there's not really much I can do, is it? 

Link to comment
Share on other sites

2 hours ago, GeraldLim said:

So there's not really much I can do, is it?

No, with root in most cases something can be done. In this case, for example, you can modify file of installed library for the game to use it. Installed library is (should be) located at the following path: "/data/app/com.happylabs.hotelstory/lib/".

Link to comment
Share on other sites

7 hours ago, CmP said:

No, with root in most cases something can be done. In this case, for example, you can modify file of installed library for the game to use it. Installed library is (should be) located at the following path: "/data/app/com.happylabs.hotelstory/lib/".

I'll give it a shot, thanks mate

Link to comment
Share on other sites

On 8/22/2021 at 12:23 PM, CmP said:

 

Update: I managed to edit the instruction values and located the values of interest. But when editing the coin value, the same happens (all coins and gems down to 0). I edited the instructions to what you told me (B0 01 C6 47 29 01 90) but it seems like the values are still being verified. 

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.