Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unstable Spellbook fast-tap exploit #827

Closed
fregkos opened this issue Sep 24, 2021 · 25 comments
Closed

Unstable Spellbook fast-tap exploit #827

fregkos opened this issue Sep 24, 2021 · 25 comments

Comments

@fregkos
Copy link

fregkos commented Sep 24, 2021

There is a case (which I encountered) where you can multi-tap an Unstable Spellbook from a quickslot with at least 2 charges and have the normal scroll activate for you while the exotic scroll dialog is still popped up. This way, even if the charge is consumed, you can still activate the exotic variety for free. Seems like a rare race condition.

@00-Evan
Copy link
Owner

00-Evan commented Sep 24, 2021

A charge is taken from the spellbook either way when the exotic version of a scroll is triggered, so this would at worse let you go to -1 charges temporarily. I'll look into this but actions that directly result from taps are usually not subject to race conditions as they all happen on the graphics thread.

@fregkos
Copy link
Author

fregkos commented Sep 24, 2021

The thing is, I was sitting at 2, then normal activation happened and went down to 1. Afterwards I clicked the exotic version and 1 charge was still remaining.

@00-Evan
Copy link
Owner

00-Evan commented Sep 24, 2021

The book must have recharged at the same time you spend a charge then, the logic is very unambiguous, 1 charge is subtracted from the current charge count if the player selects the exotic scroll.

Actually, with that in mind, how are you sure the activation order wasn't:

  • read book, get a normal scroll effect from a scroll that wasn't added to the book
  • read book again immediately after, get scroll that is in the book and get shown the window

@fregkos
Copy link
Author

fregkos commented Sep 24, 2021

Getting recharged at the same time I spend a charge could be possible. But that would not explain the remaining 1 charge, since normal + exotic = 3 charges and I was already on 2 charges. I should at least be on 0 charges, but I stayed at 1. I had no artifact recharging or ring of energy active.

I have to mention, it was a +10 book, all scrolls were added.
I suspect a race condition, because the normal scroll that was activated was Magic Mapping and the dialog was Magic Mapping & Foresight. (I've also empirically concluded that you are more likely to get the same scroll if you activate the book consecutively without moving or making any other action.)

@fregkos
Copy link
Author

fregkos commented Sep 24, 2021

I called this fast-tap exploit, but I caused it by accident, because my fingers are getting sweaty. So, I think the device registered multiple taps in incredible short amount of time. Just like when you spill water on the screen. I mean I didn't try humanly possible fast-tapping.

@00-Evan
Copy link
Owner

00-Evan commented Sep 24, 2021

(I've also empirically concluded that you are more likely to get the same scroll if you activate the book consecutively without moving or making any other action.)

That's simply incorrect, the RNG does not care at all about when two rolls are made. If this was true then you've found a security issue in Java's random number generator.

So, I think the device registered multiple taps in incredible short amount of time. Just like when you spill water on the screen. I mean I didn't try humanly possible fast-tapping.

I see, so you meant simultaneous taps, not fast taps. This gives me more to go on as this is not a race condition, simply two inputs both being registered in the same frame.

@fregkos
Copy link
Author

fregkos commented Sep 24, 2021

That's simply incorrect, the RNG does not care at all about when two rolls are made. If this was true then you've found a security issue in Java's random number generator.

Yes, this is a guess, but after so many games I get a "feeling" even about the damage calculations. I can even predict accurately if a snake would die with one shot. I'm even surprised with myself sometimes. If the random seed (for the RNG) is not periodically changed, one can "learn" the outcomes with good accuracy, given that you get a "feeling" of the seed. I know this sounds absurd, but you can experiment yourself with the book and activate it two times consecutively and picking the normal scroll (even if exotic is available). My experience says that most of the time, it'll be the same scroll, given that no other actions occur in-between. Also, isn't the Java's RNG already flawed? If I remember correctly, the game uses java.util.Random class which is based on time for the seed. It's behavior can be quite expected if you are paying attention to RNG of this game for years. If the java.util.SecureRandom class was used, which generates non-deterministic output, it would be more fun for me. But hey, that's me, other players might not notice the difference.

I see, so you meant simultaneous taps, not fast taps. This gives me more to go on as this is not a race condition, simply two inputs both being registered in the same frame.

In that case, yes, I meant simultaneous taps, just like when a liquid is spilled on screen.

@LogicalityDog
Copy link

I use a Pixel 3a, if I tab out of the game after reading the book (before selecting the scroll type) if I tab back in by pressing on the button I want it'll use that type and still allow me to use the other type. Basically I get two uses for the price of one. I'm trying to find it again in my current run to screen shot it and see if it works with other stuff too

@fregkos
Copy link
Author

fregkos commented Sep 28, 2021

So, you mean that interrupting the game while the selection dialog is open by tabbing out and in the game, allows the execution of the normal scroll (consuming no charge?) whilst dialog remains open, right?

@LogicalityDog
Copy link

That was consistently done by me during my last playthrough, yes. It only allowed me to do both options once, but it did let me pick both options. I think it only consumed charge for the second choice.

@LogicalityDog
Copy link

bug_proof

Finally was able to test and re-prove it again.
Top three images, I tried to select the advanced scroll first when I tabbed out, but instead it activated the basic version. When I tabbed back in, I couldn't select the advanced version, so it gave me two sets of normal mirror image

Bottom three images, I selected the basic scroll when tabbing back in, then was able to also select the advanced scroll. It's basically just a two-for-one deal. So far, I cannot do it multiple times with one read, so it's not super all-powerful, but it's definitely a significant buff to the book's uses

@00-Evan
Copy link
Owner

00-Evan commented Sep 29, 2021

@LogicalityDog please create a separate issue if you have a separate bug.

@LogicalityDog
Copy link

I think they're the same issue, since tabbing out and back in is equivalent to the fast tap. It's just a more reliable method to execute it

@00-Evan
Copy link
Owner

00-Evan commented Dec 1, 2021

I have made a couple tweaks to how the game handles touch input and pausing in v1.1.0. These changes weren't targeted at this bug in particular but may fix it incidentally. Can you check if the error is still present in the v1.1.0 beta?

@LogicalityDog
Copy link

LogicalityDog commented Dec 1, 2021 via email

@fregkos
Copy link
Author

fregkos commented Dec 2, 2021

Perhaps we need to run this on a Android UI test, like Android Espresso, because it's difficult to register multiple taps within the same frame by hand. I remind you that this occurs when my hands are sweaty and liquids confuse the device's digitizer. I'll see what I can do about that on the weekend. I don't have much experience with Espresso.

@00-Evan
Copy link
Owner

00-Evan commented Dec 3, 2021

I doubt an Android UI testing library would help given that the game uses no Android UI components. It's all through an openGL surface.

@fregkos
Copy link
Author

fregkos commented Dec 3, 2021

Perhaps a fast macro on an emulator then. It may also be related with the registration of multiple taps on the same frame like in #828. I'll keep an eye on that on my next runs. Otherwise, I'll need to hack some savefiles to reproduce this scenario. Do you have any auxiliary tools for that kind of testing that you'd like to share? My savefile editor script is still under development.

@00-Evan
Copy link
Owner

00-Evan commented Dec 3, 2021

Based on the reproduction from #828 I have been able to reproduce this one too! It's the same bug, tapping quickslot and movement in the same frame causes the hero to move when the second tap should be ignored (in this case as a window is being displayed, in #828 because the hero is becoming busy). Movement spends a turn in this case, which causes the spellbook to trigger the regular scroll effect, under the assumption that the player closed the window.

I'm closing this issue as its turned out to be a duplicate, will be resolved when #828 is resolved.

@00-Evan 00-Evan closed this as completed Dec 3, 2021
@fregkos
Copy link
Author

fregkos commented Jan 17, 2023

This bug is is reintroduced and observed in 1.4.3. By this, I'm referring to the bug that registers multiple calls on a supposedly single tap. Reproduction is not consistent. I have been able to accidentally reproduce it 3 times in the same run. Perhaps execution does not pause on dialog appearance. It seems that they are concurrent and order is not always guaranteed. Perhaps if the observer pattern was used in the implementation, then the dialog could be awaited and upon dismissal the execution could continue. I don't remember the current implementation.

@00-Evan
Copy link
Owner

00-Evan commented Jan 17, 2023

Please be more specific. Code suggestions are not helpful, exact reproduction steps are. What exactly are you doing, and what exactly is that input causing to happen?

@fregkos
Copy link
Author

fregkos commented Jan 17, 2023

I was not more specific because the case is exactly the same as we have discussed here last year. There is nothing new with the interaction. The only new thing today is the redesigned quickslot.

Anyway, I have a screenshot the moment it happened. I simply tapped the Unstable Spellbook from the quickslot, without even trying to glitch it.

You can see I am blinded because of SoR activation and the dialog is still open allowing me to choose. I am not sure if a charge was consumed during that.
Screenshot_2023-01-16-01-14-31-73_6f3fe77889fbecf862f7061166760abf

@00-Evan
Copy link
Owner

00-Evan commented Jan 18, 2023

So to be clear, because you still didn't actually state the full interaction:

  • you tapped on a location in the game world around the same time as you tapped a quickslot (could have been just before, just after, or simultaneously)
  • This caused the spellbook to activate AND the hero to move
  • Because time passed due to the hero moving, the psi blast scroll automatically activated, but the spellbook use window is still present and can be used

Is that correct?

@fregkos
Copy link
Author

fregkos commented Jan 21, 2023

I apologize because this time it was a little different, because I didn't try to do anything simultaneously. I only tapped the spellbook from the quickslot. No action before. No action after. I did a normal interaction, I simply tapped it. I just sat there, looking at the screen, wondering how 2 taps might have registered at the same time. Could it be that the hero did not finish walking by the time the quickslot tap action has registered? I can't be sure, I tap things fast with 2 fingers when I play. I need to pay more attention to my interactions.

I will report back if I have more insights about the interaction. Perhaps I will create a new issue if it differs. Whatever the case it might be, it somehow still exists in 1.4.3 version.

@00-Evan
Copy link
Owner

00-Evan commented Jan 21, 2023

This sounds like a separate issue then. It's not related to rapid inputs but rather to the exploit handler in the unstable spellbook somehow triggering immediately. Something must have caused the hero to yield their turn, such as pressing the wait button or refreshing the game's display.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants