Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- ⚠️I'M HOSTING AN UNOFFICIAL SERVER OF FOOLS2019! Check it out: https://fools2019.stranck.ovh
- My position is a lil bit down respect to the other years, but I'm still in top ten with a perfect score and I'm happy about that. Sadly this year I was completely busy (I had only 3 afternoons free during the week), probably with more time I would have reached that score faster. I loved anyway this challenge and I'm already in hype for fools2020, that will probably be a JVM running in a obfuscated ROP chain on a second gen Pokémon on a bgb. Actually I hope it will be a little bit short (in terms of time), because this year I got a perfect score only three hours before the event ends :(
- PLZ OPEN THIS PAGE IN A DESKTOP VIEW TO ENJOY ASCII ARTS
- Write-up:
- ██╗ ██╗██████╗ ██╗████████╗███████╗ ██╗ ██╗██████╗
- ██║ ██║██╔══██╗██║╚══██╔══╝██╔════╝ ██║ ██║██╔══██╗
- ██║ █╗ ██║██████╔╝██║ ██║ █████╗█████╗██║ ██║██████╔╝
- ██║███╗██║██╔══██╗██║ ██║ ██╔══╝╚════╝██║ ██║██╔═══╝
- ╚███╔███╔╝██║ ██║██║ ██║ ███████╗ ╚██████╔╝██║
- ╚══╝╚══╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚══════╝ ╚═════╝ ╚═╝
- FUCK THE LEADERBOARDS VIDEO WAS REALASED TOO FAST, SO HAVE A WIP OF MY WRITEUP :((
- I didn't re-read it yet, so it would probably be full of errors & stuff
- Sadly I still don't have so much time, so i'll try to do a fast write-up :(
- Oh btw, as a good Italian, my english CAN'T be good. Sorry if I mess it up, I hope you can still understand it :c
- Actually since the first approach of the game I always tried to hack stuff, so I could beat the adventure part faster.
- In particular I (tried to) hack Pokémons to my party, items (like balls) and balls in my pocket, Pokémon's EV, skipping battles by changing wBattleMode, WTW and other stuff.
- Some of them worked without problems, others (like the bicycle, pokémons over level 100, masterballs) were "sgamed" (https://www.urbandictionary.com/define.php?term=Sgamed) by the anticheat system.
- It was actually fun when TheZZAZZGlitch instantly found me cheating: https://imgur.com/8ViQ9Jg
- Btw I resolved some achievments by cheating/hacking as well. These achievments are:
- - MONSTER COACH: I've hacked my first pokémon to be level 39 and have enough XPs, then I beat a random pokémon and boom, level 40
- - SQUAD ASSEMBLED: For this one I crafted two pokémons other my starter, my plans were to use them in battles and with HMs, but it also gived me the achievment. Fun fact: idk why the server randomly removed my other two pokémons and resetted the stats for my starter :(
- - ILLUSTRATED HANDBOOK: Here I've simply put some 0xFF to the seen pokémon's flags
- - AND I'M HOOKED: Set dd0f (second pokémon species) and dcd9 (species in party) tp the ID of Metapod, then set wPartyCount to 2 and you'll get the achievment! :D
- - DOUBLE TROUBLE: I skipped the entire fight by just setting wBattleMode to 0x01 (wild battle) and then running away (I did the same for the final fight with MissingNo.)
- - WILD STREET KID: First I hacked myself A LOT of money, then I used this tactic: buy 250 of everything that's under 250 money. Then sleep and sell them when they're at at least 400 money
- - PENTAKILL: Skipped all the fight using the same method of Double Trouble
- - FLASH IS STILL USEFUL: I changed the moves of my pokémon to be flash. Ez.
- Here's how I resolved the Pwned Kingdom challenges:
- **PK1**
- The first thing I tried was to change my wXCoord to be after the two guys, but that didn't worked. I tried then more stuff like WTW and trying to be OOB.
- And then, while trying this one, I randomly found the solutions (That, seems like, it was completely unintended https://imgur.com/QsoHc93):
- - I went full up to the map, and changed my wYCoord from 0x01 to 0x00
- - I went full down, where I had wYCoord = 0x03, then I decremented it to 0x02 and I went completely up.
- - When I was in the first line (with my wYCoord = 0xFE) me and the two guards disappeared.
- - I then did one step down: I reappeared without the guards, so I walked to the end and interacted with the sign
- I was livestreaming this (you can find the clip HERE: https://youtu.be/w_8D2UI4itE ) but sadly my microphone was muted 'cuz I'm an idiot. I remember I was screaming a lot of WTFs
- **PK2**
- For PK2 my first idea was to dig into the sav file and search in the code the part where it actually copies the bytes of the map, so I could easily replace them.
- I did this entering the debugger of bgb, tracing the code until I exited the VBlank and LCD interrupts, and then checking in which routine I was.
- Then, using breakpoints on jump, I tried to reverse the "call tree" and find where the functions related to the map were called, so I could understand where the map pointer were.
- Sadly, by doing this, I hitted a far jump routine and here I gived up with this soultion.
- Instead I searched inside the pkm crystal's disassembly (https://github.com/pret/pokecrystal/blob/master/wram.asm ) any variable related to the map, and I found wMapBlocksBank. I loaded the game normally, I got the value of that variable
- and then I searched it inside the sav file. I found the same value at 3:A009 so I put a breakpoint on read on them, reloaded the map and boom: breakpoint hitted. From here I started reversing and that's what I found:
- - a000 contains a pointer to a005
- - a005 is then used to get a pointer to a011
- - wMapsEventPointer is set to a011
- - then a000 is used again to get a pointer to a005
- - then idk, after some calcs we have a pointer to a009
- - Then a009 it's user to get a0c1, the data of the map
- My first attemps after these founds were to try to change a009 to any of the near values. I was thinking that it was an array of pointer to maps, so copying the second entry onto the first one
- it should have loaded the second map. I was wrong.
- After some tries I decided to look down in the memory and I've found near the first map a pattern similar to the header of the first map. Hell yeah! I've founded the second map! Now how to load it?
- I started counting how many pointer each map header had. The first map had one pointer more than the second map. Hmmmmm.... Is it maybe that the first pointer (a000) isn't a pointer of the map,
- but a pointer to the map we want to load???
- While I was having this toughs, that beautiful man called IssoTM (he really deserve a statue) confirmed them, so I changed a000 to point to the second map and... It worked!
- **PK3**
- **PK4**
- Livestream:
- ██╗ ██╗██╗ ██╗███████╗███████╗████████╗██████╗ ███████╗ █████╗ ███╗ ███╗███████╗
- ██║ ██║██║ ██║██╔════╝██╔════╝╚══██╔══╝██╔══██╗██╔════╝██╔══██╗████╗ ████║██╔════╝
- ██║ ██║██║ ██║█████╗ ███████╗ ██║ ██████╔╝█████╗ ███████║██╔████╔██║███████╗
- ██║ ██║╚██╗ ██╔╝██╔══╝ ╚════██║ ██║ ██╔══██╗██╔══╝ ██╔══██║██║╚██╔╝██║╚════██║
- ███████╗██║ ╚████╔╝ ███████╗███████║ ██║ ██║ ██║███████╗██║ ██║██║ ╚═╝ ██║███████║
- ╚══════╝╚═╝ ╚═══╝ ╚══════╝╚══════╝ ╚═╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝
- Day1 part1 (adventure): https://www.facebook.com/stranck/videos/2183689801711426/
- Day1 part2 (adventure): https://www.facebook.com/stranck/videos/2184061688340904/
- Day2 (hacking of pk2): https://www.facebook.com/stranck/videos/2185597941520612/
- Links:
- ██╗ ██╗███╗ ██╗██╗ ██╗███████╗
- ██║ ██║████╗ ██║██║ ██╔╝██╔════╝
- ██║ ██║██╔██╗ ██║█████╔╝ ███████╗
- ██║ ██║██║╚██╗██║██╔═██╗ ╚════██║
- ███████╗██║██║ ╚████║██║ ██╗███████║
- ╚══════╝╚═╝╚═╝ ╚═══╝╚═╝ ╚═╝╚══════╝
- Hand notes: https://imgur.com/a/MEo4W7c
- Instagram: https://instagram.com/stranck/
- Telegram shitpost channel: https://t.me/Stranck
- YouTube channel: https://www.youtube.com/channel/UCmMWUz0QZ7WhIBx-1Dz-IGg
- Pk3 (c):
- ██████╗ ██╗ ██╗██████╗ ██╗ ██████╗██╗
- ██╔══██╗██║ ██╔╝╚════██╗ ██╔╝██╔════╝╚██╗
- ██████╔╝█████╔╝ █████╔╝ ██║ ██║ ██║
- ██╔═══╝ ██╔═██╗ ╚═══██╗ ██║ ██║ ██║
- ██║ ██║ ██╗██████╔╝ ╚██╗╚██████╗██╔╝
- ╚═╝ ╚═╝ ╚═╝╚═════╝ ╚═╝ ╚═════╝╚═╝ */
- #include <stdio.h>
- #include <stdint.h>
- #include <stdlib.h>
- #include <string.h>
- #include <fstream>
- #define dupDimension 16777216
- int main() {
- int i = 0;
- uint32_t a0f3 = 0x5d0b1c11;
- uint32_t a0ff = 0x7ffffb0a;
- uint32_t iter;
- printf("malloc\n");
- uint8_t * duplicates = (uint8_t *) malloc(dupDimension * sizeof(uint8_t));
- uint8_t* buffer = (uint8_t*) malloc(512 * sizeof(uint8_t));
- uint16_t index;
- uint32_t a107;
- uint32_t save; //A10E + MAX (A10B, A10D) + MIN (A10B, A10D)
- uint16_t a10b;
- uint8_t a10d;
- uint8_t a10e;
- printf("Cleaning duplicates array\n");
- memset(duplicates, 0, dupDimension);
- printf("Reading buffer file\n");
- FILE * f = fopen("buffer.bin", "rb");
- if(!f) {
- perror("Error opening buffer.bin");
- exit(1);
- }
- fread(buffer, 1, 512, f);
- fclose(f);
- printf("Starting external loop\n");
- do {
- iter = a0f3 >> 8; //The whole number
- duplicates[iter] = !duplicates[iter];
- a0f3 = (a0f3 * 0x35e79125) + 0x56596b10;
- if(!(a0ff % 10000000))
- printf("EXT %d\n", a0ff);
- } while(--a0ff);
- printf("Going to internal loop\n");
- for(i = 0; i < dupDimension; i++){
- if(duplicates[i]){
- index = 0;
- a107 = 0x1b080733;
- a10b = i & 0xff;
- a10d = (i >> 8) & 0xff;
- a10e = (i >> 16) & 0xff;
- printf("INT %d\t%x\t%x\t%x\n", i, a10b, a10d, a10e);
- do {
- a10b = (a10b / 2) * a10d + a10e;
- buffer[index] ^= a10b & 0xff;
- index++;
- index %= 0x200;
- } while(--a107);
- }
- }
- printf("Writing to file\n");
- f = fopen("out.bin", "wb");
- fwrite(buffer, 1, 512, f);
- fclose(f);
- for(index = 0; index < 512; index++)
- printf("%02x ", buffer[index]);
- putchar('\n');
- return 0;
- }
- /*
- Pk3 (java):
- ██████╗ ██╗ ██╗██████╗ ██╗ ██╗ █████╗ ██╗ ██╗ █████╗ ██╗
- ██╔══██╗██║ ██╔╝╚════██╗ ██╔╝ ██║██╔══██╗██║ ██║██╔══██╗╚██╗
- ██████╔╝█████╔╝ █████╔╝ ██║ ██║███████║██║ ██║███████║ ██║
- ██╔═══╝ ██╔═██╗ ╚═══██╗ ██║ ██ ██║██╔══██║╚██╗ ██╔╝██╔══██║ ██║
- ██║ ██║ ██╗██████╔╝ ╚██╗╚█████╔╝██║ ██║ ╚████╔╝ ██║ ██║██╔╝
- ╚═╝ ╚═╝ ╚═╝╚═════╝ ╚═╝ ╚════╝ ╚═╝ ╚═╝ ╚═══╝ ╚═╝ ╚═╝╚═╝
- */
- //I tried to implement a multithread version on java, that could speed up the process a little bit (Even if we're limited by the single buffer, that does a coil whine), but I failed because java wasn't getting the inner LCG calcs right idk why. I think that's maybe because java doesn't have unsigned numbers.
- package fools2019;
- import java.io.IOException;
- import java.nio.file.Files;
- import java.nio.file.Paths;
- public class Pk3 implements Runnable{
- public static int a0f3 = 0x5d0b1c11;
- public static int a0ff = 0x7ffffb0a;
- public static byte[] buffer = new byte[512]; // A567
- public static boolean firstTime = true;
- public static synchronized int generateA0F3(){
- if(--a0ff == 0) done();
- if(a0ff % 5000 == 0) System.out.println("Remaining: " + a0ff);
- if(firstTime){
- firstTime = false;
- return a0f3;
- }
- return a0f3 = (a0f3 * 0x35e79125) + 0x56596b10;
- }
- public static synchronized void updateBuffer(int index, short a10b){
- buffer[index] ^= a10b;
- }
- public static void done(){
- try {
- Files.write(Paths.get("out.bin"), buffer);
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- System.out.println("DONE");
- for(int index = 0; index < 512; index++) {
- System.out.println(buffer[index]);
- }
- System.exit(0);
- }
- public static void main(String[] args) throws Exception{
- buffer = Files.readAllBytes(Paths.get("buffer.bin"));
- int threads = Integer.parseInt(args[0]);
- for(int i = 0; i < threads; i++)
- new Thread(new Pk3()).start();
- }
- @Override
- public void run(){
- int a107;
- short a10b; // WorkingWord
- byte a10d;
- byte a10e;
- int index;
- int a0f3;
- //boolean b;
- while(true){
- a0f3 = generateA0F3();
- a107 = 0x200;
- a10b = (short) ((a0f3 >> 8) & 0xff);
- a10d = (byte) ((a0f3 >> 16) & 0xff);
- a10e = (byte) ((a0f3 >> 24) & 0xff);
- System.out.print((long) (a0f3 & 0xFFFFFF) + " " + a10b + " " + a10d + " " + a10e);
- index = 0;
- //b = true;
- do {
- a10b = (short) ((a10b / 2) * a10d + (short)(a10e & 0xffff));
- updateBuffer(index, (short) (a10b & 0xff));
- /*if(b){
- System.out.println(" " + Integer.toHexString((int)(a10b & 0xffff)));
- b = false;
- }*/
- index++;
- index %= 0x200;
- } while(a107-- == 0);
- }
- }
- }
- //Here instead I was trying to see if there are any duplicates in THE WHOLE generated number by the external LCG. Guess who failed
- package fools2019;
- public class Pk3Dup {
- public static final int MAX_LIMIT = 100000000;
- public static void main(String[] args){
- int a0ff = 0x7ffffb0a;
- int a0f3 = 0x5d0b1c11;
- int i, max = 0;
- Result r;
- Result[] res = new Result[MAX_LIMIT];
- do{
- for(i = 0; i < MAX_LIMIT; i++){
- r = res[i];
- if(r == null){
- res[i] = new Result(a0f3);
- //System.out.println("adding " + a0f3);
- max++;
- break;
- } else if(r.n == a0f3){
- r.attempt++;
- System.out.println("DUPLICATE: " + a0f3);
- break;
- }
- }
- a0f3 = (a0f3 * 0x35e79125) + 0x56596b10;
- if(a0ff % 10000 == 0) System.out.println(a0ff + " " + max);
- }while(a0ff-- != 0);
- }
- }
- package fools2019;
- public class Result {
- public int n;
- public int attempt;
- public Result(int n){
- this.n = n;
- }
- }
- /*
- Sym file:
- ███████╗██╗ ██╗███╗ ███╗ ███████╗██╗██╗ ███████╗
- ██╔════╝╚██╗ ██╔╝████╗ ████║ ██╔════╝██║██║ ██╔════╝
- ███████╗ ╚████╔╝ ██╔████╔██║ █████╗ ██║██║ █████╗
- ╚════██║ ╚██╔╝ ██║╚██╔╝██║ ██╔══╝ ██║██║ ██╔══╝
- ███████║ ██║ ██║ ╚═╝ ██║ ██║ ██║███████╗███████╗
- ╚══════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝╚══════╝╚══════╝
- 01:D922 loadPointerLoop
- 01:D932 loadPointerLoop
- 02:B765 loadFullPointer
- 03:A084 copy4DEtoHL
- 03:A090 addFromDE
- 03:A0A0 tripleRST38
- 03:A0A4 callerADDFROMDE-A0A0
- 03:A0AB secondPartCounters
- 03:A0BC addDEdata2
- 03:A0C4 secondPart
- 03:A0DA possible2loop
- 03:A0F3 keyISuppose
- 03:A107 counters
- 03:A10B hlResultPep1loopEnd
- 03:A10F possibleEntryPoint1
- 03:A126 pep1loop
- 03:A12A pep1loop.end
- 03:A13A beforeEndPlusWrite
- 03:A15A possibleEntryPoint2
- 03:A16F pep2.skip
- 03:A179 pep2.end
- 03:A567 pk3MAP
- 00:1898 entryPoint
- 02:ADFB afterText
- 02:AE11 possibleEntryPoint
- 02:AE14 hereWeGo
- 02:B0B3 startDEdata
- 03:A100 possibleSaveData
- Notes:
- ███╗ ██╗ ██████╗ ████████╗███████╗███████╗
- ████╗ ██║██╔═══██╗╚══██╔══╝██╔════╝██╔════╝
- ██╔██╗ ██║██║ ██║ ██║ █████╗ ███████╗
- ██║╚██╗██║██║ ██║ ██║ ██╔══╝ ╚════██║
- ██║ ╚████║╚██████╔╝ ██║ ███████╗███████║
- ╚═╝ ╚═══╝ ╚═════╝ ╚═╝ ╚══════╝╚══════╝
- wNumKeyItems
- wMoney
- wPartyMonNicknames
- wBattleMode
- Move4: DCE4
- CUT: 0F
- SURF: 39
- FLASH: 94
- DelayFrames END 046E
- */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement