HTTP/1.1 200 OK
Content-Type: application/json
Date: Sat, 26 Aug 2023 08:31:05 GMT
Connection: keep-alive
Keep-Alive: timeout=5
Content-Length: 198
{"characters":[{"name":"......... .........","cardName":"....................................","rarity":"2*","attribute":"Cute","splashArt":"warm-camping-style","avatar":"warm-camping-style-icon"}]}
Interesting.. I'll save this for later - back to the code.
There's another function called DisplaySplashArt, which has a different method to display each card, depending on the rarity.
public IEnumerator DisplaySplashArt(Character[] characters)
{
int i;
Func<bool> <>9__0;
int j;
for (i = 0; i < characters.Length; i = j + 1)
{
if (this.skipClicked)
{
this.skipClicked = false;
break;
}
if (characters[i].rarity == "4*")
{
base.StartCoroutine(this.DisplayFourStarCharacter(characters[i]));
}
else if (characters[i].rarity == "3*")
{
base.StartCoroutine(this.DisplayThreeStarCharacter(characters[i]));
}
else
{
base.StartCoroutine(this.DisplayTwoStarCharacter(characters[i]));
}
yield return new WaitForEndOfFrame();
Func<bool> func;
if ((func = <>9__0) == null)
{
func = (<>9__0 = () => this.CheckForSkipOrClick(characters, i));
}
yield return new WaitUntil(func);
if (!this.skipClicked)
{
AudioController.Instance.PlaySFX("Touch");
}
j = i;
}
this.DisplayGachaOverview();
yield break;
}
Comparing the methods, we see that the DisplayFourStarCharacter has an interesting section of code.
string flag = character.flag;
if (flag != null)
{
byte[] array = Convert.FromBase64String(flag);
Texture2D texture2D = new Texture2D(2, 2);
texture2D.LoadImage(array);
Rect rect = new Rect(0f, 0f, (float)texture2D.width, (float)texture2D.height);
Vector2 vector = new Vector2(0.5f, 0.5f);
Sprite sprite = Sprite.Create(texture2D, rect, vector);
this.flagImage.sprite = sprite;
}
Looks like all we need to do is get a 4-star card and we've solved the challenge! First, I patched the code so that all cards would be processed as 4-star (I thought maybe the 2-3 star characters could still have a flag property, that wasn't being extracted/displayed). The patched code looked like:
public IEnumerator DisplaySplashArt(Character[] characters)
{
int i;
int j;
for (i = 0; i < characters.Length; i = j + 1)
{
if (this.skipClicked)
{
this.skipClicked = false;
break;
}
if (characters[i].rarity == "4*")
{
base.StartCoroutine(this.DisplayFourStarCharacter(characters[i]));
}
else if (characters[i].rarity == "3*")
{
base.StartCoroutine(this.DisplayFourStarCharacter(characters[i]));
}
else
{
base.StartCoroutine(this.DisplayFourStarCharacter(characters[i]));
}
yield return new WaitForEndOfFrame();
yield return new WaitUntil(() => this.CheckForSkipOrClick(characters, i));
if (!this.skipClicked)
{
AudioController.Instance.PlaySFX("Touch");
}
j = i;
}
this.DisplayGachaOverview();
yield break;
}
It didn't work though - we saw from the web request that the cards are returned from the server though, this isn't going to be a client-side trick. Maybe we just need to brute-force until we get it? Well, we can check the game rules and find that the odds are as follows.
4 star = 0%
3 star = 8.5%
2 star = 91.5%
Sounds like we have literally zero chance of getting a 4 star card. I decided to copy the HTTP request we found earlier to burp suite and play around with the values. After a few attempts I came across this one.