Jump to content

EvillyG00d

Senior Member
  • Posts

    12
  • Joined

  • Last visited

Everything posted by EvillyG00d

  1. I think the last time I checked in, you guys were at around 60k - this is incredible! Congratulations to everyone involved I see a lot of old friendly faces on the Mod team and it brings me a lot of joy to see DiDA and the rest of the Mod team be so successful. Keep doing what you guys are doing - this is just the beginning! Hope you all are having a fantastic 2015
  2. ✻ Requirements File browser Hex Editor Decimal to Hex Converter: http://www.binaryhexconverter.com/decimal-to-hex-converter Hex to Decimal Converter: http://www.binaryhexconverter.com/hex-to-decimal-converter ✻ Gathering Data For this tutorial I’m going to use Candy Crush Saga. I’ll be changing lives, score, and stars. Hex editing requires you to play the game’s first few levels so actual data shows up in the .dat file, unlike .plist editing which usually already has the parameters setup whether you’ve played or not. So the first thing I’m going to do is play the first 3 levels of the game. My sav.dat file looks like this (sadly my hex editor doesn’t allow copy-paste, so I’ll be using screenshots): In the case of Candy Crush, the FFs and 00s are placeholders. If you want to enter new data, you would do so in between and not overwrite the placeholders. Some apps are different and require you to write over the 00s. It’s a toss-up which system apps use, so make sure you backup your .dat file, as picking the wrong one usually results in a crash and/or data wipe. Alternatively you could play the game a bit further until you figure out which is correct. Here are my stats from playing the first 3 levels: 4 lives Level 1 score: 3000 (3 stars) Level 2 score: 8220 (3 stars) Level 3 score: 12980 (3 stars) ✻ Procedure Taking the data above and converting it to hex yields: 04 lives Level 1 score: 0BB8 (03 stars) Level 2 score: 201C (03 stars) Level 3 score: 32B4 (03 stars) Compare that with the screenshot of the sav.dat file. There is a single 04 toward the top, next to all the FFs. That must be our lives. We can change it to FF to make it 255. Toward the bottom there are a few 03s. Those must be our stars, and it’s only logical our score is nearby. Candy Crush is a good example of an app that uses reverse hex! As you can see, the level scores are listed as B80B, 1C20, and B432. Some apps use regular hex and others use reverse - it’s another toss-up which app uses which, so write down both variants so you can search for both. Hex can only be broken down into bytes, which is 2 digits (called bits). This is why “reversed” hex isn’t completely reversed. Here’s an example: Normal: 12 34 Reversed (incorrect): 43 21 Reversed (correct): 34 12 /* It helps to break the hex into chunks of 2-digits to see the pattern better */Now that it’s confirmed the reversed values are truly the scores, we can edit them to, say, FF FF FF (16,777,215). Remember that Candy Crush wants us to write in between the placeholders. In other words, there should always be two sets of 00 between the score and stars: Old score: B8 0B 00 00 03 New score (incorrect): FF FF FF 00 03 New score (correct): FF FF FF 00 00 03 /* Remember that other apps have these outcomes flipped, so remember to try both and backup your .dat file */
  3. ✻ Requirements IDA (demo works fine) Hex Editor ARM-to-Hex Converter Cracked App Binary ✻ ARM Architecture I assume you already know how to crack an app and get the binary into IDA with the proper settings. The programming language that we'll be working with is called ARM. Each line is formatted like this: Header Rn, Operand2 What you need to remember is that each line (called an "instruction") is read from right to left. Here's some examples: MOV R0, R1 /* This is read as move (MOV) the value of R1 to R0 */ LDR R3, R0 /* Load (LDR) the value of R0 into R3 */ There are many other complicated instructions, such as vectors, that I will not be covering in this tutorial. In this tutorial I'll show examples including ADD, SUB, MOV, LDR, STR, NOP, BX LR, CMP, and branches. 99% of the time those will be the only headers you'll use when hacking. At first look IDA can seem complex, but the actual hacking portion is repetitive, and usually doesn't take more than the 8-10 headers I'll explain here. The following examples are real. I wanted to include the whole function so you get an idea of how many instructions you have to sort through. Some are quite long, but I hope you learn from them. It may be helpful to also have this page open when you read through the examples. ✻ Addition and Subtracting (ADD, SUB) These headers are probably the easiest to comprehend because I assume you’ve already been acquainted with basic arithmetic. Have a look at the example below. It is sub_X and GDB dropped me off at address 0x003B9156 (marked with <<<). The thing we are trying to hack is ammo. When you shoot a gun, it subtracts a bullet. We should be looking for a SUB that has 1 associated with it. 0x003B9150 seems to fit the description (marked with ~~~). It can either be changed to a ADDS R0, #1 or NOP. A NOP is an instruction that tells the code to skip the instruction - it’s a nothing or a null. You don’t have to worry about memorizing the S-suffix. ADD and ADDS are written the same in hex. Operand2 dictates if the S-suffix is used or not. If Operand2 is a register, there is no S-suffix. If Operand2 is a number, there is an S-suffix. This applies to all headers. ADD R0, R1 ADDS R0, #1 __text:003B90EE loc_3B90EE ; CODE XREF: sub_3B8B4C+55Ej __text:003B90EE ; sub_3B8B4C+564j ... __text:003B90EE MOV R0, #(off_4AC64C - 0x3B90FA) ; off_4AC64C __text:003B90F6 ADD R0, PC __text:003B90F8 LDR R0, [R0] ; byte_6FFAFC __text:003B90FA LDRB.W R0, [R0,#0x50] __text:003B90FE CMP R0, #0 __text:003B9100 BNE loc_3B9156 __text:003B9102 LDR.W R0, [R10,#8] __text:003B9106 MOVW R2, #0x61A8 __text:003B910A CMP R0, #1 __text:003B910C ITT GE __text:003B910E SUBGE R0, #1 __text:003B9110 STRGE.W R0, [R10,#8] __text:003B9114 LDR.W R1, [R10,#0xC] __text:003B9118 MOVS R0, #0 __text:003B911A CMP R1, R2 __text:003B911C IT LT __text:003B911E MOVLT R0, #1 __text:003B9120 CMP R1, #1 __text:003B9122 BLT loc_3B9156 __text:003B9124 ORRS R0, R6 __text:003B9126 CMP R0, #1 __text:003B9128 BNE loc_3B9156 __text:003B912A CMP R6, #1 __text:003B912C BNE loc_3B914C __text:003B912E BL sub_1A7F30 __text:003B9132 VLDR S0, =100.0 __text:003B9136 VMOV D1, R0, R0 __text:003B913A VCMPE.F32 S2, S0 __text:003B913E VMRS APSR_nzcv, FPSCR __text:003B9142 BMI loc_3B914C __text:003B9144 LDR.W R0, [R10] __text:003B9148 CMP R0, #0x28 __text:003B914A BNE loc_3B9156 __text:003B914C __text:003B914C loc_3B914C ; CODE XREF: sub_3B8B4C+5E0j __text:003B914C ; sub_3B8B4C+5F6j __text:003B914C LDR.W R0, [R10,#0xC] __text:003B9150 SUBS R0, #1 ~~~~ __text:003B9152 STR.W R0, [R10,#0xC] __text:003B9156 __text:003B9156 loc_3B9156 ; CODE XREF: sub_3B8B4C+5B4j __text:003B9156 ; sub_3B8B4C+5D6j ... __text:003B9156 MOVS R0, #1 <<< __text:003B9158 STR.W R0, [R10,#4] __text:003B915C LDR.W R0, [R10,#8] __text:003B9160 CMP R0, #0 __text:003B9162 BEQ loc_3B9184 __text:003B9164 MOVW R0, #(:lower16:(off_4AC504 - 0x3B9172)) __text:003B9168 CMP R4, #1 __text:003B916A MOVT.W R0, #(:upper16:(off_4AC504 - 0x3B9172)) __text:003B916E ADD R0, PC ; off_4AC504 __text:003B9170 LDR R0, [R0] ; dword_85F8DC __text:003B9172 BNE loc_3B9200 __text:003B9174 LDR R0, [R0] __text:003B9176 LDR.W R1, [R10] __text:003B917A CMP R1, #0x2B __text:003B917C BNE loc_3B9204 __text:003B917E ADDW R0, R0, #0x44C __text:003B9182 B loc_3B9224 __text:003B9184 ; --------------------------------------------------------------------------- ✻ Data Handling (MOV, LDR, STR) Data handling headers are probably the most common headers used when hacking. A move (MOV) simply moves a value into another register. Loaders (LDR) load a value into a register - this is the same as MOV but Operand2’s value remains. A store (STR) is the reverse of LDR - it tells the value of Rn to be stored into Operand2. STR is the only header that is read left to right (that I know of anyways). Have a look at the STR instruction in the example (marked by <<<). It says, “Store the value of R1 in R0+1C”. It’s worth noting at this point that R7 holds the value of 803 million. I’m not sure why, but it really comes in handy. It’s also important to remember that the first Rn in the function is usually where title-name property is stored (in this case, stars). With those two things in mind, look at the example below. The function name is AwardStars - it’s job must be to load the user’s current star count (hence all the LDRs and STRs). The first instruction is hackable (marked with ~~~)! Instead of loading R0+1C (whatever that is) into our stars register, why not R7? Replace the LDR instruction with MOV R2, R7. This function can also be hacked by the STR instruction (marked by <<<). Remember, the LDR loaded R0+1C into our stars, and since LDR doesn’t wipe R0+1C’s value, R0+1C is unchanged. Therefore, both R0+1C and R2 must equal the same thing. Furthermore, R0+1C must also equal our stars. A bit confusing, but the hard part is now over. Simply change the STR to STR R7, [R0,#0x1C], which reads “Store the value of R7, or 803 million, into R0+1C”. __text:00061E0C ; Player_AwardStar(SPlayer *, int) __text:00061E0C __Z16Player_AwardStarP7SPlayeri ; CODE XREF: L_SceneManager_AwardPlayerReward(SSceneManager *,int,ESceneRewardType,SNpcInstance *)+ECp __text:00061E0C ; L_SceneManager_TriggerReward(SSceneManager *,SSceneReward *)+FAp ... __text:00061E0C LDR R2, [R0,#0x1C] ~~~ __text:00061E0E ADD R1, R2 __text:00061E10 STR R1, [R0,#0x1C] <<< __text:00061E12 LDR R0, [R0] __text:00061E14 MOVS R1, #0 __text:00061E16 B.W __Z24SceneManager_MarkForSaveP13SSceneManageri ; SceneManager_MarkForSave(SSceneManager *,int) __text:00061E16 ; End of function Player_AwardStar(SPlayer *,int) Now let’s look at hacking a LDR. The example below is from the same app and has a similar name: AwardEnergy. If the function behaved itself, we could replace the first two instructions (marked with <<<) with MOV R0, R7 followed by BX LR. A BX LR tells the code to skip all the way to next function. So what we’d be doing is telling 803 million to move into R0 (energy) and skip to the next function - done. That WOULD work except there are some branches in the function. It’s usually not appropriate to BX LR before a branch. As I explain in the next example, a branch is a boolean - if you skip that boolean the code effectively nulls both true and false, which most of the time results in a crash. If you’re familiar with Pay2Win games, you’ll know that energy is a bit more complex than a currency value because of timer checks. I’m guessing that’s why there are branches, and nulling those would crash the app. So what we have to do is hack the LDR function (marked with ~~~). We know that R0 is our energy, and similar to the AwardStars LDR instruction, this LDR is asking for R4+30. If it’s changed to MOV R0, R7, 803 million will be loaded into energy and all is well. __text:00061DD4 ; Player_AwardEnergy(SPlayer *, unsigned int, int) __text:00061DD4 __Z18Player_AwardEnergyP7SPlayerji ; CODE XREF: Player_Update(SPlayer *,int)+3F2p __text:00061DD4 ; L_SceneManager_AwardPlayerReward(SSceneManager *,int,ESceneRewardType,SNpcInstance *)+D4p ... __text:00061DD4 PUSH {R4,R7,LR} <<< __text:00061DD6 MOV R4, R0 <<< __text:00061DD8 ADD R7, SP, #4 __text:00061DDA LDR R0, [R4,#0x30] ~~~ __text:00061DDC CBNZ R2, loc_61DF0 __text:00061DDE LDR R2, [R4,#0x34] __text:00061DE0 CMP R0, R2 __text:00061DE2 BHI loc_61DEA __text:00061DE4 ADDS R3, R0, R1 __text:00061DE6 CMP R3, R2 __text:00061DE8 BCS loc_61E06 __text:00061DEA __text:00061DEA loc_61DEA ; CODE XREF: Player_AwardEnergy(SPlayer *,uint,int)+Ej __text:00061DEA CMP R0, R2 __text:00061DEC IT CS __text:00061DEE POPCS {R4,R7,PC} __text:00061DF0 __text:00061DF0 loc_61DF0 ; CODE XREF: Player_AwardEnergy(SPlayer *,uint,int)+8j __text:00061DF0 ADD R0, R1 __text:00061DF2 STR R0, [R4,#0x30] __text:00061DF4 MOV R0, R4 __text:00061DF6 BL __Z27L_Player_ResizeEnergyButtonP7SPlayer ; L_Player_ResizeEnergyButton(SPlayer *) __text:00061DFA LDR R0, [R4] __text:00061DFC MOVS R1, #0 __text:00061DFE POP.W {R4,R7,LR} __text:00061E02 B.W __Z24SceneManager_MarkForSaveP13SSceneManageri ; SceneManager_MarkForSave(SSceneManager *,int) __text:00061E06 ; --------------------------------------------------------------------------- __text:00061E06 __text:00061E06 loc_61E06 ; CODE XREF: Player_AwardEnergy(SPlayer *,uint,int)+14j __text:00061E06 STR R2, [R4,#0x30] __text:00061E08 POP {R4,R7,PC} __text:00061E08 ; End of function Player_AwardEnergy(SPlayer *,uint,int) ✻ Branches (unconditional, conditional) Branches do what they sound like: They tell the code to branch off in 1 or 2 directions. There are two types of branches: unconditional and conditional. Unconditional branches are B and BL - they branch in 1 direction. Branch (B ) tells the code to jump to an address INSIDE the housing function. The last instruction in the example function is a Branch. A Branch Link (BL) is a branch that tells the code to jump to an address OUTSIDE the housing function. There are multiple BLs in the example and are beside text (this text is the address destination). Conditional branches are everything else - BEQ, BNZ, BLT, etc. They always follow a Compare (CMP), which dictates what happens when the code comes to the branch. Let’s have a look at the first branch in the example (marked by <<<). The CMP instruction reads, “compare the number 0 with R0”. A BEQ (branch if equal) follows the CMP, saying, “If the number 0 is equal to R0, branch to address 0x1002E0”. That’s how all conditional branches work - the key is to remember instructions are read right to left. That doesn’t matter for BEQ, but when you do BLT and BGT, it is crucial. Now that you now how branches work, let’s hack this function. The function name, CanLearnSkill, is a boolean (hence all the branches). In the game, you can only learn skills if you have skill points. We want to remove that restriction so you can learn skills regardless of skill points! Look at the first 4 conditional branches (marked with <<<). They all tell the code to branch to 0x1002E0 if their Rn equals 0. Zero you say? Sounds like our skill points. Judging by the rest of the branches, this is highly likely. Have a look at 0x1002E0 (marked with ~~~). Remember that in numeric code, 0=false and 1=true. MOV R0,#0 is a very common way of writing false, or in other words, NOPE. If however the instruction is changed to MOV R0,#1 we’ll always be able to learn skills. It all makes sense now: If R0, R3, R4 equal 0 (all checks and balances for skill points), branch to MOV R0,#1, which tells the code TRUE/YES: you CAN learn skills on 0. The following instruction (LDMFD SP!, {R4-R7,PC}) is a reset - it tells the code to pop back to the beginning of the function. Remember that the MOV R0,#1 is only called when Rn is 0, so this doesn’t affect the learning of skills with non-zero skill points. __text:00100234 ; CMvPlayer::CanLearnSkill(CMvSkill *, bool) __text:00100234 EXPORT __ZN9CMvPlayer13CanLearnSkillEP8CMvSkillb __text:00100234 __ZN9CMvPlayer13CanLearnSkillEP8CMvSkillb __text:00100234 ; CODE XREF: CMvSkill::DrawExplainPopup(bool,bool)+40p __text:00100234 ; CMvSkill::DrawIcon(CGsDrawRect *,int,int,bool)+6Cp ... __text:00100234 STMFD SP!, {R4-R7,LR} __text:00100238 ADD R7, SP, #0xC __text:0010023C LDR R3, [R0] __text:00100240 MOV R6, R0 __text:00100244 MOV R5, R1 __text:00100248 UXTB R4, R2 __text:0010024C LDR R3, [R3,#0x24] __text:00100250 BLX R3 __text:00100254 CMP R0, #0 <<< __text:00100258 BEQ loc_1002E0 <<< __text:0010025C CMP R4, #0 <<< __text:00100260 BEQ loc_100274 <<< __text:00100264 MOV R3, #0x69A __text:00100268 LDRH R3, [R6,R3] __text:0010026C CMP R3, #0 <<< __text:00100270 BEQ loc_1002E0 <<< __text:00100274 __text:00100274 loc_100274 ; CODE XREF: CMvPlayer::CanLearnSkill(CMvSkill *,bool)+2Cj __text:00100274 CMP R5, #0 <<< __text:00100278 BEQ loc_1002E0 <<< __text:0010027C MOV R0, R5 __text:00100280 MOV R1, #0xFFFFFFFF __text:00100284 LDRB R4, [R5,#5] __text:00100288 BL __ZN8CMvSkill12LoadMaxLevelEi ; CMvSkill::LoadMaxLevel(int) __text:0010028C CMP R4, R0 __text:00100290 BGE loc_1002E0 __text:00100294 B loc_1002E8 __text:00100298 ; --------------------------------------------------------------------------- __text:00100298 __text:00100298 loc_100298 ; CODE XREF: CMvPlayer::CanLearnSkill(CMvSkill *,bool)+CCj __text:00100298 MOV R1, #0xFFFFFFFF __text:0010029C MOV R0, R5 __text:001002A0 BL __ZN8CMvSkill17LoadLimitPreSkillEi ; CMvSkill::LoadLimitPreSkill(int) __text:001002A4 CMN R0, #1 __text:001002A8 MOV R1, R0 __text:001002AC MOVEQ R0, #1 __text:001002B0 LDMEQFD SP!, {R4-R7,PC} __text:001002B4 MOV R0, R6 __text:001002B8 BL __ZN9CMvPlayer14SearchSkillPtrEi ; CMvPlayer::SearchSkillPtr(int) __text:001002BC CMP R0, #0 __text:001002C0 BEQ loc_1002E0 __text:001002C4 LDRSB R3, [R0,#4] __text:001002C8 CMN R3, #1 __text:001002CC BLE loc_1002E0 __text:001002D0 LDRB R0, [R0,#5] __text:001002D4 SUBS R0, R0, #0 __text:001002D8 MOVNE R0, #1 __text:001002DC LDMFD SP!, {R4-R7,PC} __text:001002E0 ; --------------------------------------------------------------------------- __text:001002E0 __text:001002E0 loc_1002E0 ; CODE XREF: CMvPlayer::CanLearnSkill(CMvSkill *,bool)+24j __text:001002E0 ; CMvPlayer::CanLearnSkill(CMvSkill *,bool)+3Cj ... __text:001002E0 MOV R0, #0 ~~~ __text:001002E4 LDMFD SP!, {R4-R7,PC} __text:001002E8 ; --------------------------------------------------------------------------- __text:001002E8 __text:001002E8 loc_1002E8 ; CODE XREF: CMvPlayer::CanLearnSkill(CMvSkill *,bool)+60j __text:001002E8 MOV R0, R5 __text:001002EC MOV R1, #0xFFFFFFFF __text:001002F0 LDRB R4, [R6,#0x40F] __text:001002F4 BL __ZN8CMvSkill18LoadLimitCharLevelEi ; CMvSkill::LoadLimitCharLevel(int) __text:001002F8 CMP R4, R0 __text:001002FC BLT loc_1002E0 __text:00100300 B loc_100298 __text:00100300 ; End of function CMvPlayer::CanLearnSkill(CMvSkill *,bool) ✻ Special Thanks mikeyb123 - For sharing his offsets of High School Story, which helped me with LDRs. More IDA tutorials: http://iosgods.com/topic/660-tutorial-ida-hacking-tutorial-1/
  4. ✻ Requirements ✔ Mobile Substrate ✔ Mobile Terminal ✔ BigBoss Recommended Tools ✔ Theos ✔ iOS SDK ✻ Setup Variants From my experience, setting up theos is a *****. My 3 iDevices all have different theos/SDK variants because while something may work on one device, it may not work on another. In the future I may write a theos/SDK error list with solutions, but right now I really don’t have the expertise to talk about that, especially considering I have a broken theos now that I can’t seem to fix. If you are having similar issues, I recommend following this guide: https://iosgods.com/topic/62343-new-2021-ios-1213-how-to-install-theos-sdk-on-your-idevice/ ✻ Setting Up a Project Launch Mobile Terminal and sign in as root. Then type this command: $THEOS/bin.nic.pl /* If that results in error, type /var/theos/bin/nic.pl */ This command starts up the New Instance Creator (nic). Next, choose iphone/tweak by typing the number associated with it. Lastly, name your project (herein myhack), bundle ID, and author. The last too are only important if you plan on publishing your tweak to Cydia. If you’re not, feel free to leave them blank. Note this puts myhack in /var/mobile. If you want it in a different directory, cd it before starting up nic. In /myhack, there are 3 files of interest. The Makefile, myhack.plist, and Tweak.xm. The Makefile is where you would add frameworks or instructions for the installation process. myhack.plist contains a list of app bundle IDs the hack will target. To fetch a bundle ID, go into /Library/Preferences of your app and copy the com.companyName.appName.plist (exclude the .plist extension). That is the bundle ID. If you’re app doesn’t have that file in /Preferences, go to /appName.app and open up Info.plist. The bundle ID will be in <string>Bundle Identifier</string>. If you want the hack to work on all apps, delete the myhack.plist. ✻ Tweak.xm This is where the code is written. The file already has an example written for you. Since it is commented out, feel free to keep it there for reference - it will not affect your code. The way MS hook hacks are made is by calling both a header and a method, and altering them. I recommend using Flex to find headers and methods. It’s by far the most convenient program to use, considering you can search all headers at once and you don’t need to crack the app. If you prefer a command-line program, use class dump. If you notice a lack of unique headers/methods, the app is sub_X. MS hooking will not work with this app and you’ll either need to use symbol hooking or code injection. Here are some examples on how to return each method type: int, double, and long long -(int)coins { return 999999; } /* doubles and long longs are returned the same way, just replace (int) with (double) or (long long). The return value must be an integer - no decimals */ float -(float)coins { return 999.9f; } bool -(bool)hasCoins { return TRUE; } /* must be true/false value. Can also be written as yes/no */ id -(id)coins { return [NSNumber numberWithInteger:999999]; } /* id’s can be anything - a number, bool, string, etc. You have to call the correct NSClass to hack it correctly. These are very rare - I myself have never had to hack one */ void -(void)showCoins { } /* This is a nulled method. Standalone-voids cannot be returned */ void with argument -(void)setCoins:(int)argument { argument = 999999; } -(void)setHasCoins:(bool)argument { argument = TRUE; } -(void)setCoins:(id)argument { argument = [NSNumber numberWithInteger:999999]; } /* “argument” can be named anything. This is similar to returning non-void counterparts, except you name the argument and remove “return” */ ✻ Adding UI Popup This is really handy against leechers. Adding a popup is relatively simple, and requires changes to both the Makefile and Tweak.xm. First, use Flex (or class dump) to find method -(void)applicationDidBecomeActive:(id). It's usually in a header file called AppDelegate. Now add this to your Tweak.xm (remember to edit the header accordingly): %hook AppDelegate -(void)applicationDidBecomeActive:(id)argument { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"This is the Title" message:@"This is the Message" delegate:nil cancelButtonTitle:@"This is the Button Text" otherButtonTitles:nil]; [alert show]; [alert release]; } %end /* Sometimes attaching the popup to this method results in a crash. You can attach the popup to any void you want, but attaching it to the launch method is the most convenient for both you and the user */ If you were to compile myhack now, the compiler would not understand what UIAlertView is and would return an error. To fix this, import the UIKit framework in your Makefile. Add this line below the myhack_FILES line: myhack_FRAMEWORKS = UIKit You can now compile. ✻ Compiling In MobileTerminal, cd to your project folder. Then, type any of these commands: make /* Makes the .dylib */ make package /* Makes a .deb for easy install */ make package install /* Makes a .deb and installs it for you */ The .dylib will appear in /myhack/obj. The .deb will appear in /myhack and install to /Library/MobileSubstrate/DynamicLibraries. Extra info by @castix (post😞 So because this tutorials is already awesome (big shoutout to evilg00d there) I will just add some notes As he already mentioned in the main topic here, you can't override void but you can NULL them = disable them - (void)enemiesShoots { //This is the method that calls your opponents to shoot so if we disable this, they can't anymore } if you want to add this in a patcher, you can simply write it like this - (void)enemyShoots { //Easy isn't it ? if(GetPrefBool(@"kEnemyShooting")) { return; } return %orig; } Moving on there are some more value classes, which can be modified - (long long)Coins { //This can obviously be treated like int return 2222; } - (double)Coins { //You can also see here that it can be overwritten really easy return 2222; } Those are just a few more function methods , so if you find something like them in FLEX/Headers/Binaries you know what do do. Step-by-step tutorial on how to make a Preference Bundle (Patcher with on/off settings) here: http://iosgods.com/topic/444-tutorial-how-to-make-a-preference-bundle/
  5. ✻ Requirements ✔ Charles Proxy ✔ An internet connection that both your computer and iDevice can connect to simultaneously ✔ Sample .xml template: http://www.solidfiles.com/d/471b9a0957/ ✻ Overall Structure Start by loading up the sample .xml template with your text editor. There are multiple ways to write these up - for this tutorial I chose the format Charles itself uses when exporting .xml projects. The one thing these .xml files will always have in common are hosts and rules. The host's job is to tell Charles Proxy where to look when hacking the app. The hacking, or edits, is the rule's job. ✻ Finding Your Host Connect your iDevice to Charles by entering your computer's IP address into your iDevice's HTTP Proxy. Once connected, launch the app you want to hack. For this tutorial, we'll be hacking Blitz Brigade. Please note this hack currently doesn't work, as Gameloft has shut down their "Free Gems" option for the time being (probably because of this exploit). Check out Charles on your computer - the left side of the Charles window should be loading up all kinds of URLs. Those are your hosts! Back in the sample .xml template, find the <host> tags. Replace HOST URL with ingameads.gameloft.com. Sometimes, we'll want to specify in a bit more detail where Charles should look. So, in the <path> tags, replace PATH TO TARGET with /redir/appleads*. The asterisk is a wildcard - it tells Charles to look at everything within that directory path. There are other times however, when adding a specific path is not necessary, in which case we remove the <path> tags altogether. ✻ Finding Your Rule The host you choose will often dictate what rule you will use to hack the app. With Blitz Brigade, we'll be using the AdColony reward_amount rule, which is why we used hosts that correlated with AdColony (or "in game ads"). In the <matchValue> tags, replace NORMAL/UNCHANGED VALUE with "reward_amount":1. Remember that watching videos yields 1 Gem, that's why we put the value 1. In the <newValue> tags, replace HACKED VALUE with "reward_amount":999999. You're done! ✻ Conclusion Here's the completed .xml for Blitz Brigade: http://www.solidfiles.com/d/075eb25b88/ To load it up in Charles Proxy, go to Tools > Rewrite. Click the "Import" button and select the .xml you downloaded above. Click "Apply" and then "OK". You're hack is in place and ready to go! Ensure you're still connected with your iDevice and press the "Free Gems" button to watch a video. Once done, you should receive 100,000 Gems.
  6. ✻ Requirements ✔ Command-line Tool (Putty for Windows; Terminal for Mac) ✔ Memory Access Tool (iGameGuardian, Gameplayer, Gamegem) ✔ OpenSSH (available on BigBoss) ✔ GNU-Debugger (available on cydia.radare.org) ✻ Procedure Firstly, use your memory access tool to find the address of your target (herein “coins”). If the tool you are using cannot find the address, this guide is not for you. There is another method to GDB hacking called breakpointing for this case, but I don’t know how to do it. If I learn it I will be sure to share it. Once you have your address, load up your command-line tool and SSH to your device. To start GDB, follow the commands: gdb /* Loads up GDB */ att pid /* This means attach process ID. If you don’t know it, the app binary usually works too. This command will freeze the app so values do not change */ watch *0xADDRESS /* Sets a watchpoint to your address, where “ADDRESS” is what you found with Gameplayer */ continue /* Unfreezes the app */ Now it’s your job to change the value of coins, just like you would if hacking with Gameplayer. Once the value changes, the app should freeze because you set a watchpoint on coins. GDB will give you some tasty information now - in your command prompt, you should see the old value and new value of coins. You’ll also be given the “real” address of coins, which can be plugged into IDA (remember, addresses in your memory access tool are temporary and change every launch. The address GDB gives you is consistent until the app is updated). ✻ Other Useful Commands ps ax /* Loads all processes and their IDs */ display /i $pc /* Type this after watchpointing. It tells GDB to automatically show the address’ function when frozen */ info r /* Gives you the current value held in registers 0-12 */ stepi /* Shows you the next function */ ✻ TroubleshootingGDB is not attaching when I use the app binary name - why? Using the binary name doesn’t always work. To get the processor ID, quit GDB by simply typing “quit” and then type “ps ax” (no quotes). That will bring up all running processes on your device. Look for the one in /var/mobile/Applications - the pid is listed on the left. When attaching a process, I get “Segmentation fault:11” and get kicked back to root - why? The app you are trying to debug has anti-debug security. To get around this you’ll have to disable ptrace in IDA. I will not cover that in this guide, perhaps in another. It isn’t a very common issue at the moment, I’ve only seen Gameloft and TinyCo. use it. GDB didn’t freeze when the value changed - why? This bugged me all the time, and King Kong was nice enough to help me find a solution. It’s quite simple actually, just control+c to make Putty/Terminal give you back the command-line. From there, re-enter the watchpoint command and type continue. The new value and address should now pop up without even needing to change it again in-game. The address GDB gave me isn’t a hackable function - why? The address GDB spits out isn’t always the function to hack. Load up IDA and have a look around the address - most of the time the function you want to hack is above the address given to you. Remember there are multiple ways to hack a function, it really depends on how well you know ARM. ✻ Special Thanks King Kong - For helping me on ptrace and freezing apps!
×
  • Create New...

Important Information

We would like to place cookies on your device to help make this website better. The website cannot give you the best user experience without cookies. You can accept or decline our cookies. You may also adjust your cookie settings. Privacy Policy - Guidelines