Skip to content

Commit

Permalink
Unlim bytes and some menu changes
Browse files Browse the repository at this point in the history
  • Loading branch information
joeyjurjens committed Apr 4, 2020
1 parent 98e3a27 commit 3adf193
Show file tree
Hide file tree
Showing 8 changed files with 174 additions and 127 deletions.
55 changes: 31 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,26 +20,29 @@
* Backend Offset Patcher Switch is based on [KittyMemory](https://github.com/MJx0/KittyMemory)
* Original bytes are <b>not</b> required
* Supports MSHookMemory
* Write unlimited bytes to a offset

* Open Source Menu

<br>

### Installation:

Download/clone this project and copy the .tar file to '$THEOS/templates/ios' & then run nic.pl to create a project <br>
You can download the template here: [Latest Release](github.com/joeyjurjens/iOS-Mod-Menu-Template-for-Theos/releases/latest). <br>
<b>Also follow the instructions below otherwise you will run into errors!<b> <br>
<b>iOS:</b>
1. In the makefile on line 22, you've to set the path to your SDK. This menu has been tested with the "iPhoneOS11.2.sdk" SDK from [theos/sdks](https://github.com/theos/sdks)
2. I use initializer_list in this project, iOS doesn't have this included by itself. You can download it [<b>here</b>](https://raw.githubusercontent.com/joeyjurjens/iOS-Mod-Menu-Template-for-Theos/977e9ff2c626d6b1308eed7e17f1daf0a610e8e9/template/KittyMemory/initializer_list), save it as "initializer_list" and copy the file to: "$THEOS/sdks/iPhoneOS11.2.sdk/usr/include/c++/4.2.1/" <br>

<b>MacOS:</b>
1. In the Makefile of the project, change "MOBILE_THEOS=1" to "MOBILE_THEOS=0" on line 19 of the makefile. <br>
1. Install xCode if you haven't already.
1. In the Makefile of the project, change "MOBILE_THEOS=1" to "MOBILE_THEOS=0" on line 19 of the makefile. <br>

### Usage:

<b> Changing the menu images </b>

Inside tweak.xm, you'll setup the menu under the function "setupMenu".
Inside the tweak.xm, you'll setup the menu under the function "setupMenu".
Here you'll see two options under the menu: menuIcon & menuButton, those require a base64 image string.
In order to get a base64 string from the image, upload the image here: https://www.browserling.com/tools/image-to-base64

Expand All @@ -49,39 +52,40 @@ Images 50x50 are recommended, you can get a sample of my images by copying the s

<b> Patching a offset without switch: </b>
```c
patchOffset(0x1002DB3C8, 0xC0035FD6);
patchOffset(0x10020D2D3, 0x00008052C0035FD6);
```
patchOffset(0x1002DB3C8, "0xC0035FD6");
patchOffset(0x10020D2D4, "0x00008052C0035FD6");

// You can write as many bytes as you want to an offset
patchOffset(0x10020D3A8, "0x00F0271E0008201EC0035FD6");
```
<b> Offset Patcher Switch: </b> <br>
<b> Note </b>: "Bytes" allow up to <b> two </b> arm instructions per offset, not more. <br>
<b> Offset Patcher Switch: </b>
```obj-c
[switches addOffsetSwitch:@"One Hit Kill"
description:@"Enemy will die instantly!"
offsets:{0x1001BB2C0, 0x1002CB3B0}
bytes:{0x00E0BF12C0035FD6, 0xC0035FD6}];
[switches addOffsetSwitch:@"One Hit Kill"
description:@"Enemy will die instantly"
offsets:{0x1001BB2C0, 0x1002CB3B0, 0x1002CB3B8}
bytes:{"0x00E0BF12C0035FD6", "0xC0035FD6", "0x00F0271E0008201EC0035FD6"}];
```

<b> Empty Switch: </b>
```obj-c
[switches addSwitch:@"Anti Ban"
description:@"You can't get banned, keep this enabled!"];
[switches addSwitch:@"Masskill"
description:@"Teleport all enemies to you without them knowing"];
```
<b> Textfield Switch: </b>
```obj-c
[switches addTextfieldSwitch:@"Custom Gold: "
description:@"Here you can enter your own gold amount!"
inputBorderColor:[UIColor colorWithRed:0.74 green:0.00 blue:0.00 alpha:1.0]];
[switches addTextfieldSwitch:@"Custom Gold"
description:@"Here you can enter your own gold amount"
inputBorderColor:UIColorFromHex(0xBD0000)];
```
<b> Slider Switch: </b>
```obj-c
[switches addSliderSwitch:@"Custom Move Speed: "
description:@"Set your custom move speed!"
minimumValue:0
maximumValue:10
sliderColor:[UIColor colorWithRed:0.74 green:0.00 blue:0.00 alpha:1.0]];
[switches addSliderSwitch:@"Custom Move Speed"
description:@"Set your custom move speed"
minimumValue:0
maximumValue:10
sliderColor:UIColorFromHex(0xBD0000)];
```
<b> Checking if a switch is on:
```obj-c
Expand Down Expand Up @@ -110,12 +114,15 @@ The sample.xm in the project shows an example project.
* Me
* [MJx0](https://github.com/MJx0)
* For [KittyMemory](https://github.com/MJx0/KittyMemory)
* For contributions
* [bR34Kr](https://github.com/bR34Kr)
* For contributions
* [dogo](https://github.com/dogo)
* For [SCLAlertView](https://github.com/dogo/SCLAlertView)
<br>
### Contact:
If you have any questions, suggestions, bugs or anything else:
If you need support, you may discord me.
However, please don't spam me and give me as much information you can when you do so.
<br> <b>Discord:</b> Joey#0309
Binary file removed Ted2's Mod Menu Template.nic.tar
Binary file not shown.
28 changes: 17 additions & 11 deletions template/Macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
//

#include "Menu.h"
#import "KittyMemory/writeData.hpp"

#include <substrate.h>
#include <mach-o/dyld.h>

Expand All @@ -19,19 +21,23 @@ extern Switches *switches;
#define HOOK(offset, ptr, orig) MSHookFunction((void *)getRealOffset(offset), (void *)ptr, (void **)&orig)
#define HOOK_NO_ORIG(offset, ptr) MSHookFunction((void *)getRealOffset(offset), (void *)ptr, NULL)

// Convert hex color to UIColor, usage: For the color #BD0000 you'd use: UIColorFromHex(0xBD0000)
#define UIColorFromHex(hexColor) [UIColor colorWithRed:((float)((hexColor & 0xFF0000) >> 16))/255.0 green:((float)((hexColor & 0xFF00) >> 8))/255.0 blue:((float)(hexColor & 0xFF))/255.0 alpha:1.0]

uint64_t getRealOffset(uint64_t offset){
return _dyld_get_image_vmaddr_slide(0) + offset;
}

/*
Patching a offset without switch.
*/
bool patchOffset(uint64_t offset, unsigned long long data) {
if(data < 0xFFFFFFFF) {
data = _OSSwapInt32(data);
return MemoryPatch(NULL,offset, &data, sizeof(uint32_t)).Modify();
} else {
data = _OSSwapInt64(data);
return MemoryPatch(NULL,offset, &data, sizeof(uint64_t)).Modify();
}
// Patching a offset without switch.
void patchOffset(uint64_t offset, std::string hexBytes) {
if(isValidHexString(hexBytes)) {
std::vector<uint32_t> hexBytesVector = getHexBytesVector(hexBytes);
for(int i = 0; i < hexBytesVector.size(); i++) {
if(!writeData32(offset + (i * 4), hexBytesVector[i])) {
[menu showPopup:@"Something went wrong!" description:[NSString stringWithFormat:@"Something went wrong while patching this offset: %llu", offset]];
}
}
} else {
[menu showPopup:@"Invalid Hex" description:[NSString stringWithFormat:@"Failing offset: 0x%llx, please re-check the hex you entered.", offset]];
}
}
9 changes: 6 additions & 3 deletions template/Menu.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,20 @@

-(void)showMenuButton;
-(void)addSwitchToMenu:(id)switch_;
-(void)showPopup:(NSString *)title_ description:(NSString *)description_;

@end

@interface OffsetSwitch : UIButton

- (id)initHackNamed:(NSString *)hackName_ description:(NSString *)description_ offsets:(std::vector<uint64_t>)offsets_ bytes:(std::vector<uint64_t>)bytes_;

- (id)initHackNamed:(NSString *)hackName_ description:(NSString *)description_ offsets:(std::vector<uint64_t>)offsets_ bytes:(std::vector<std::string>)bytes_;

-(NSString *)getPreferencesKey;
-(NSString *)getDescription;
- (std::vector<MemoryPatch>)getMemoryPatches;
std::string getNonHexString(std::string hexString);
bool isValidHexString(std::string hexString);
std::vector<uint32_t> getHexBytesVector(std::string hexString);


@end
Expand Down Expand Up @@ -65,7 +68,7 @@

-(void)addSwitch:(NSString *)hackName_ description:(NSString *)description_;

- (void)addOffsetSwitch:(NSString *)hackName_ description:(NSString *)description_ offsets:(std::initializer_list<uint64_t>)offsets_ bytes:(std::initializer_list<uint64_t>)bytes_;
- (void)addOffsetSwitch:(NSString *)hackName_ description:(NSString *)description_ offsets:(std::initializer_list<uint64_t>)offsets_ bytes:(std::initializer_list<std::string>)bytes_;

- (void)addTextfieldSwitch:(NSString *)hackName_ description:(NSString *)description_ inputBorderColor:(UIColor *)inputBorderColor_;

Expand Down
72 changes: 51 additions & 21 deletions template/Menu.mm
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ @implementation Menu
NSString *menuIconBase64;
NSString *menuButtonBase64;
float scrollViewHeight = 0;
BOOL hasRestoredLastSession = false;
UIButton *menuButton;

UIWindow *mainWindow;

Expand Down Expand Up @@ -130,17 +132,22 @@ - (void)hideMenu:(UITapGestureRecognizer *)tap {
if(tap.state == UIGestureRecognizerStateEnded) {
[UIView animateWithDuration:0.5 animations:^ {
self.alpha = 0.0f;
menuButton.alpha = 1.0f;
}];
}
}

-(void)showMenu:(UITapGestureRecognizer *)tapGestureRecognizer {
if(tapGestureRecognizer.state == UIGestureRecognizerStateEnded) {
menuButton.alpha = 0.0f;
[UIView animateWithDuration:0.5 animations:^ {
self.alpha = 1.0f;
}];

}
// We should only have to do this once (first launch)
if(!hasRestoredLastSession) {
restoreLastSession();
hasRestoredLastSession = true;
}
}

Expand Down Expand Up @@ -178,7 +185,7 @@ -(void)showMenuButton {
NSData* data = [[NSData alloc] initWithBase64EncodedString:menuButtonBase64 options:0];
UIImage* menuButtonImage = [UIImage imageWithData:data];

UIButton *menuButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
menuButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
menuButton.frame = CGRectMake((mainWindow.frame.size.width/2), (mainWindow.frame.size.height/2), 50, 50);
menuButton.backgroundColor = [UIColor clearColor];
[menuButton setBackgroundImage:menuButtonImage forState:UIControlStateNormal];
Expand Down Expand Up @@ -279,28 +286,27 @@ -(void)switchClicked:(id)switch_ {

@implementation OffsetSwitch {
NSString *preferencesKey;
std::vector<uint64_t> offsets;
std::vector<uint64_t> bytes;
std::vector<MemoryPatch> memoryPatches;
UILabel *offsetPatchSwitch;
NSString *description;
}

- (id)initHackNamed:(NSString *)hackName_ description:(NSString *)description_ offsets:(std::vector<uint64_t>)offsets_ bytes:(std::vector<uint64_t>)bytes_ {
offsets = offsets_;
bytes = bytes_;
- (id)initHackNamed:(NSString *)hackName_ description:(NSString *)description_ offsets:(std::vector<uint64_t>)offsets_ bytes:(std::vector<std::string>)bytes_ {
description = description_;
preferencesKey = hackName_;

// For each offset, we create a MemoryPatch.
for(int i = 0; i < offsets.size(); i++) {
if(bytes[i] < 0xFFFFFFFF) {
bytes[i] = _OSSwapInt32(bytes[i]);
memoryPatches.push_back(MemoryPatch(NULL,offsets[i], &bytes[i], sizeof(uint32_t)));
} else {
bytes[i] = _OSSwapInt64(bytes[i]);
memoryPatches.push_back(MemoryPatch(NULL,offsets[i], &bytes[i], sizeof(uint64_t)));
}
for(int i = 0; i < offsets_.size(); i++) {
int offsetCount = i;
if(isValidHexString(bytes_[i])) {
std::vector<uint32_t> hexBytesVector = getHexBytesVector(bytes_[i]);
for(int i = 0; i < hexBytesVector.size(); i++) {
uint32_t hexBytes = _OSSwapInt32(hexBytesVector[i]);
memoryPatches.push_back(MemoryPatch(NULL,offsets_[offsetCount] + (i * 4), &hexBytes, sizeof(uint32_t)));
}
} else {
[menu showPopup:@"Invalid Hex" description:[NSString stringWithFormat:@"Failing offset: 0x%llx, please re-check the hex you entered.", offsets_[offsetCount]]];
}
}

self = [super initWithFrame:CGRectMake(-1, scrollViewX + scrollViewHeight - 1, menuWidth + 2, 50)];
Expand Down Expand Up @@ -346,6 +352,33 @@ -(NSString *)getDescription {
return memoryPatches;
}

std::string getNonHexString(std::string hexString) {
std::string firstTwoCharacters = hexString.substr(0, 2);
if(firstTwoCharacters == "0x") {
hexString.erase(0,2);
}
hexString.erase(remove(hexString.begin(), hexString.end(), ' '), hexString.end());
return hexString;
}

bool isValidHexString(std::string hexString) {
hexString = getNonHexString(hexString);
if(hexString.size() == 0 || hexString.size() % 8 != 0) {
return false;
}
return true;
}

std::vector<uint32_t> getHexBytesVector(std::string hexString) {
std::vector<uint32_t> stringHexBytes;
std::string nonHexString = getNonHexString(hexString);
for(int i = 0; i <= nonHexString.size() - 1; i+=8) {
std::string byteString = nonHexString.substr(i, 8);
stringHexBytes.push_back(strtoull(byteString.c_str(), nullptr, 16));
}
return stringHexBytes;
}

@end //end of OffsetSwitch class


Expand Down Expand Up @@ -534,14 +567,14 @@ @implementation Switches


-(void)addSwitch:(NSString *)hackName_ description:(NSString *)description_ {
OffsetSwitch *offsetPatch = [[OffsetSwitch alloc]initHackNamed:hackName_ description:description_ offsets:std::vector<uint64_t>{} bytes:std::vector<uint64_t>{}];
OffsetSwitch *offsetPatch = [[OffsetSwitch alloc]initHackNamed:hackName_ description:description_ offsets:std::vector<uint64_t>{} bytes:std::vector<std::string>{}];
[menu addSwitchToMenu:offsetPatch];

}

- (void)addOffsetSwitch:(NSString *)hackName_ description:(NSString *)description_ offsets:(std::initializer_list<uint64_t>)offsets_ bytes:(std::initializer_list<uint64_t>)bytes_ {
- (void)addOffsetSwitch:(NSString *)hackName_ description:(NSString *)description_ offsets:(std::initializer_list<uint64_t>)offsets_ bytes:(std::initializer_list<std::string>)bytes_ {
std::vector<uint64_t> offsetVector;
std::vector<uint64_t> bytesVector;
std::vector<std::string> bytesVector;

offsetVector.insert(offsetVector.begin(), offsets_.begin(), offsets_.end());
bytesVector.insert(bytesVector.begin(), bytes_.begin(), bytes_.end());
Expand All @@ -550,7 +583,6 @@ - (void)addOffsetSwitch:(NSString *)hackName_ description:(NSString *)descriptio
[menu addSwitchToMenu:offsetPatch];
}


- (void)addTextfieldSwitch:(NSString *)hackName_ description:(NSString *)description_ inputBorderColor:(UIColor *)inputBorderColor_ {
TextFieldSwitch *textfieldSwitch = [[TextFieldSwitch alloc]initTextfieldNamed:hackName_ description:description_ inputBorderColor:inputBorderColor_];
[menu addSwitchToMenu:textfieldSwitch];
Expand All @@ -561,7 +593,6 @@ - (void)addSliderSwitch:(NSString *)hackName_ description:(NSString *)descriptio
[menu addSwitchToMenu:sliderSwitch];
}

// get value from textfield or slider
- (NSString *)getValueFromSwitch:(NSString *)name {

//getting the correct key for the saved input.
Expand All @@ -578,7 +609,6 @@ - (NSString *)getValueFromSwitch:(NSString *)name {
return 0;
}

// this method can be used to check whether a switch is on or not!
-(bool)isSwitchOn:(NSString *)switchName {
return [[NSUserDefaults standardUserDefaults] boolForKey:switchName];
}
Expand Down
Loading

0 comments on commit 3adf193

Please sign in to comment.