ThauEx / ffrk-proxy

Proxy for Final Fantasy Record Keeper written in node.js
GNU Lesser General Public License v3.0
39 stars 21 forks source link

Enhancement: EXP boost #27

Closed jdel closed 7 years ago

jdel commented 8 years ago

I have recently got Cid's Ace Pilot and noticed that at least a line change in the json battle dump when you are granted the 200% EXP bonus.

The value 101 under buddy_boost_exp_map is changed from 'null' to 200.

I have tried to change value in buddy.js using: json[buddy_boost_exp_map].params[101] = '200';

But the battle doesn't start and I get error messsage 4033.

Do you guys think this is something we could exploit in order to level up faster ?

ThauEx commented 8 years ago

json['buddy_boost_exp_map'].params[101] = '200';

jdel commented 8 years ago

AAhhh god dammit, it's still too early for me... will give it a shot. cheers.

jdel commented 8 years ago

Still get the 4033 error straight away. I suspect there are other values to change somewhere. I will do some tests tonight running the same battle in fabul castle until I get the exp boost and then do a diff with the dump files.

ThauEx commented 8 years ago

Don't know if this helps, but there is a file called testBuddy.js in the tests folder, it can be used to test the modifications on a dump.

jdel commented 8 years ago

I will check tonight.

KHShadowrunner commented 8 years ago

Just to save you guys the hassle, I've already played with it.

There's 2 parts that get modified, as you've found obviously the materia section of the code and the exp bonus bundle. You need to have both for it to boost. You can't modify the materia bonus from 20 to anything else, say 100, without it crashing - so that might be where you're having problems. You can however modify the value, so instead of 200 in the materia section you could put it at 400, and same with the xp bonus. As long as you modify that xp bonus section, you get the visual prompt that Ace Pilot has triggered.

Alas, the bad news - Even if you do this, there's a lot of missing code that doesn't get added. There's no visual effect for the XP bonus taking effect, so that doesn't show. And that'd be a lot of code to add. More importantly, even if you do trigger it, the XP bonus is handled on the server side - that is to say that even if we got the stars to align and get all of the changed parts put in, the game would still not actually upgrade the values (sort of like how we can't change how much gold actually drops).

Unfortunately for us, it makes it pretty negligable as to how useful Ace is with the proxy.

But what it does let us do, is assign ace to a character and then change the materia in-battle to do something else.The options here are endless, I use it for zealot. It's basically just a free 20% chance of double XP.

jdel commented 8 years ago

Thanks a lot @KHShadowrunner, this seemed obvious that exp is handled server side, but I thought I'd give it a shot anyways. Now we know it is definitely going to work :)

Happy to close this issue if we cannot find any use for the Ace Pilot materia.

KHShadowrunner commented 8 years ago

There might have been something I missed, some setting that could be done. Maybe we do really have to add the graphics for it triggering? All signs point to it not working, but. Just figured I'd comment that based on everything I've seen, the server handles if the exp actually gets doubled. Hmmm... I wonder now. What if we did look at ALL of the things that change and try to impose them in...

There's a lot to it though, again every graphic has its own for the bar increment. I wouldn't close this yet as maybe there is deeper to dig.

The ultimate conclusion to this is in what packet is sent back to the server after completion. If it's just a "clear" code, there's no need to chase it. But if the packet we sent back actually says how much of what we get - there could be something to it.

jdel commented 8 years ago

Is there any way to turn this ffrk-proxy in debug / verbose mode, to dump all the packets /json exchanged with the server in order to investigate what's in them ?

ThauEx commented 8 years ago

Sadly not. For most requests the whitelist is used, which mean no mitm -> not able to see the content of the request. Only for battles mitm is used and this is already dumped to the dump folder. The game is using https, so everything is encrypted.

KHShadowrunner commented 8 years ago

So I can't in the mitm proxy. I can in fiddler/FFRKInspector. But at the end of the day, it doesn't make a difference. There is a json string for the win - and I've tried to modify it. It very much looks like you should be able to adjust the information - but all it does is allow you to modify the win screen (and I haven't actually had any success with that, just no code error with what I wrote). Which is great, looks cool, but I'm 99% sure it's all still handled server side. There might be a thing or two to test, and if you're interested I can give you the code snippets that I used to try and add growth eggs to the rewards screen (And a dump of the json code embedded in the win packet). But the win packet has an excrypted section which is what I assume is sent to the server. :( bummer.

Still, you can tinker with it and see what you find! Let me know :)

jdel commented 8 years ago

Yeah why not, doesn't hurt to at least give it a try !

ThauEx commented 8 years ago

Looks interesting... At least there is something with gold and exp

KHShadowrunner commented 8 years ago

new 1.txt

Attached should hopefully be the snippit back from the server for win. The issue comes in the response that we give back as seen here:

new 2.txt

KHShadowrunner commented 8 years ago

I'm pretty sure we sent an encrypted response to winning, and then we get back a json that contains what's needed for the win screen. Least that's what I discovered. I added a whole bunch of stuff to try and add growth eggs (had to create 2 new json, one for adding assets and one for modifying the results section to include the drops). But... no eggs lol

We could try to play around with the EXP, but it gets a little mathy and I figured it would not actually change it.

But. Hats off if you go for it.

ThauEx commented 8 years ago

Hm.. the response from the second one is base64 encoded and encrypted...

ThauEx commented 8 years ago

I found some code regarding the encryption, but had no time to analyse it..

var h=n.CipherParams=r.extend(
            {
            init:function(e)
                {
                this.mixIn(e)
            }
            ,toString:function(e)
                {
                return(e||this.formatter).stringify(this)
            }
        }
        ),f=(t.format=
            {
        }
        ).OpenSSL=
            {
            stringify:function(e)
                {
                var t=e.ciphertext;
                return e=e.salt,(e?i.create([1398893684,1701076831]).concat(e).concat(t):t).toString(o)
            }
            ,parse:function(e)
                {
                e=o.parse(e);
                var t=e.words;
                if(1398893684==t[0]&&1701076831==t[1])
                    {
                    var n=i.create(t.slice(2,4));
                    t.splice(0,4),e.sigBytes-=16
                }
                return h.create(
                    {
                    ciphertext:e,salt:n
                }
                )
            }
        }
        ,p=n.SerializableCipher=r.extend(
            {
            cfg:r.extend(
                {
                format:f
            }
            ),banish:function(e,t,n,r)
                {
                r=this.cfg.extend(r);
                var i=e.createEncryptor(n,r);
                return t=i.finalize(t),i=i.cfg,h.create(
                    {
                    ciphertext:t,key:n,iv:i.iv,algorithm:e,mode:i.mode,padding:i.padding,blockSize:e.blockSize,formatter:r.format
                }
                )
            }
            ,dispel:function(e,t,n,r)
                {
                return r=this.cfg.extend(r),t=this._parse(t,r.format),e.createDecryptor(n,r).finalize(t.ciphertext)
            }
            ,_parse:function(e,t)
                {
                return"string"==typeof e?t.parse(e,this):e
            }
        }
        ),t=(t.kdf=
            {
        }
        ).OpenSSL=
            {
            execute:function(e,t,n,r)
                {
                return r||(r=i.random(8)),e=u.create(
                    {
                    keySize:t+n
                }
                ).compute(e,r),n=i.create(e.words.slice(t),4*n),e.sigBytes=4*t,h.create(
                    {
                    key:e,iv:n,salt:r
                }
                )
            }
        }
        ,d=n.PasswordBasedCipher=p.extend(
            {
            cfg:p.cfg.extend(
                {
                kdf:t
            }
            ),banish:function(e,t,n,r)
                {
                return r=this.cfg.extend(r),n=r.kdf.execute(n,e.keySize,e.ivSize),r.iv=n.iv,e=p.banish.call(this,e,t,n.key,r),e.mixIn(n),e
            }
            ,dispel:function(e,t,n,r)
                {
                return r=this.cfg.extend(r),t=this._parse(t,r.format),n=r.kdf.execute(n,e.keySize,e.ivSize,t.salt),r.iv=n.iv,p.dispel.call(this,e,t,n.key,r)
            }
        }
        )

It's from https://ffrk.denagames.com/dff/static/ww/compile/en/js/lib.js And use http://matthewfl.com/unPacker.html to decode it.

KHShadowrunner commented 8 years ago

Now that's interesting. I wonder what we could do... would need to try and get a decrypted result and see if we could re-encrypt it and send it with modified data lol

ThauEx commented 7 years ago

I'm closing this, because I'm not playing the game anymore and don't have time to work on this feature.