# TBCMailServer
A private server for the mailbox in The Battle Cats.
It allows you to get any cat, talent orb, or item amount you want without
the ban risk of other methods.
[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/fieryhenry)
## Credits
- [jamesiotio's CITM](https://github.com/jamestiotio/CITM) for the original
hacking method and the format of the presents. It no longer works due to
PONOS adding a signature to the server responses as well as other changes.
## Prerequisites
I won't go into detail on how to do all of the individual steps such as how to
extract the apk, sign it and setup Frida. You can find tutorials on how to do
all of that online.
1. You will need to modify the game to always verify the
nyanko-signature of the server responses as we don't know PONOS's private
key. This can be done using [Frida](https://frida.re/) and this script:
```js
let func_name = "_ZN5Botan11PK_Verifier14verify_messageEPKhmS2_m" // 64 bit
// or
let func_name = "_ZN5Botan11PK_Verifier14verify_messageEPKhjS2_j" // 32 bit
// Botan::PK_Verifier::verify_message(...)
Interceptor.attach(Module.findExportByName("libnative-lib.so", func_name), {
onLeave: function (retval) {
retval.replace(0x1)
}
})
```
Alternativly you can patch the libnative-lib.so file using a hex editor to
make the function always return 1.
1. You also need to replace the `https://nyanko-items.ponosgames.com` URL in
the libnative-lib.so files with your own server URL. This can be done by
extracting the APK using something like
[apktool](https://ibotpeaches.github.io/Apktool/) or
[APKToolGui](https://github.com/AndnixSH/APKToolGUI)
1. Then you can modify the `libnative-lib.so` files in the `lib` folder using a
hex editor (or notepad maybe).
1. Then you can repack the APK using apktool and sign it using
[apksigner](https://developer.android.com/studio/command-line/apksigner) or
[APKToolGui](https://github.com/AndnixSH/APKToolGUI).
1. The URL needs to be the same length as the original URL and it needs to have
/items/ at the end with underscores padding the rest of the URL.
The underscores are used to make the URL the same length as the original URL.
The URL also needs to start with https and so you can use a service like
[Serveo](https://serveo.net/) to do the https part for you. Just follow the
instructions on the website. I recommend you to get a custom subdomain so it
doesn't change (you can use any subdomain as long as the total url length is
shorter than the original URL).
Example:
You can run a command like: `ssh -R myserver:80:localhost:80 serveo.net`
You may need to setup ssh keys for the above to work (follow the given
instructions) This makes your url: `https://myserver.serveo.net` and then you
would replace the ponos url with `https://myserver.serveo.net/items/_`.
Instead of using a private server, you might be able to use something like
[mitmproxy](https://mitmproxy.org/) or [Fiddler](https://www.telerik.com/fiddler)
to modify the server responses. This did not work for me as the game always
crashed (works for other requests though) but it might work for you.
## Installation
1. Install [Python](https://www.python.org/downloads/) >= 3.9
1. Run `pip install -U tbcms`
## Usage
1. Run `python -m tbcms` or `py -m tbcms` depending on
your system.
1. Run `python -m tbcms --help` for more information.
1. Read [jamesiotio's CITM](https://github.com/jamestiotio/CITM) on how to
format the list of presents.
1. Create a file called `presents.json` somewhere and put your presents in it.
1. Run `python -m tbcms --presents path/to/presents.json` to start
server.
Example presents.json
```json
[
{
"id": 1,
"title": "Items",
"body": "Test Body",
"createdAt": 1688648392,
"items": [
{
"itemId": 22,
"itemCategory": 0,
"amount": 50,
"title": "Catfood"
},
{
"itemId": 29,
"itemCategory": 0,
"amount": 5,
"title": "Platinum Ticket"
}
]
}
]
```
## Alternative Method
You can also change the public key the game uses to verify the server responses
to your own public key from a key pair you generated.
You can modify the `assets/nyanko-service-prd.pem` file in the APK to use your own
public key. You can generate a key pair using openssl:
```sh
openssl genrsa -out private.pem 4096
openssl rsa -in private.pem -pubout -out public.pem
```
The problem with this method is that you now need to intercept or use a private
server for every single request that uses the public key as now the game will
reject the official server responses from PONOS.
However, I did still manage to do all of that, but the game refused to upload
the save data to the game servers. It does a request to an aws server but it
aborts immediately after. I couldn't have changed the url of the server it
uploads to to my own server because the url is from a response of another
request with a signature that I don't know how to generate.
Another problem is that if you have a request with more than one slash in the
same place, serveo.net will respond with a 301 Moved Permanently and redirect to
the url with only one slash. But if the original request was a POST request,
the method will change to GET and break the request. If it instead used a 308
Permanent Redirect then it would keep the method as POST and it would work.
When downloading save data, PONOS accidentally has 2 slashes in the same place.
I don't know how to fix this.
I know that this is not a Flask issue because Flask responds correctly with a
308 Permanent Redirect. I think it is a problem with serveo.net.
It's probably possible to do this method but I can't be bothered to do it.
Even though this alternative method is not effective, I spent a lot of time on it
so I wanted to include it here.
Raw data
{
"_id": null,
"home_page": "https://github.com/fieryhenry/tbcms",
"name": "tbcms",
"maintainer": "",
"docs_url": null,
"requires_python": ">=3.9",
"maintainer_email": "",
"keywords": "",
"author": "fieryhenry",
"author_email": "",
"download_url": "https://files.pythonhosted.org/packages/e5/71/1e4b94a9f5be7fc80f70f4a1d5f93580e189755dbb00f62f32a792788b0f/tbcms-1.0.0.tar.gz",
"platform": null,
"description": "# TBCMailServer\n\nA private server for the mailbox in The Battle Cats.\n\nIt allows you to get any cat, talent orb, or item amount you want without\nthe ban risk of other methods.\n\n[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/fieryhenry)\n\n## Credits\n\n- [jamesiotio's CITM](https://github.com/jamestiotio/CITM) for the original\n hacking method and the format of the presents. It no longer works due to\n PONOS adding a signature to the server responses as well as other changes.\n\n## Prerequisites\n\nI won't go into detail on how to do all of the individual steps such as how to\nextract the apk, sign it and setup Frida. You can find tutorials on how to do\nall of that online.\n\n1. You will need to modify the game to always verify the\n nyanko-signature of the server responses as we don't know PONOS's private\n key. This can be done using [Frida](https://frida.re/) and this script:\n\n ```js\n let func_name = \"_ZN5Botan11PK_Verifier14verify_messageEPKhmS2_m\" // 64 bit\n // or\n let func_name = \"_ZN5Botan11PK_Verifier14verify_messageEPKhjS2_j\" // 32 bit\n\n // Botan::PK_Verifier::verify_message(...)\n Interceptor.attach(Module.findExportByName(\"libnative-lib.so\", func_name), {\n onLeave: function (retval) {\n retval.replace(0x1)\n }\n })\n ```\n\n Alternativly you can patch the libnative-lib.so file using a hex editor to\n make the function always return 1.\n\n1. You also need to replace the `https://nyanko-items.ponosgames.com` URL in\n the libnative-lib.so files with your own server URL. This can be done by\n extracting the APK using something like\n [apktool](https://ibotpeaches.github.io/Apktool/) or\n [APKToolGui](https://github.com/AndnixSH/APKToolGUI)\n1. Then you can modify the `libnative-lib.so` files in the `lib` folder using a\n hex editor (or notepad maybe).\n1. Then you can repack the APK using apktool and sign it using\n [apksigner](https://developer.android.com/studio/command-line/apksigner) or\n [APKToolGui](https://github.com/AndnixSH/APKToolGUI).\n1. The URL needs to be the same length as the original URL and it needs to have\n /items/ at the end with underscores padding the rest of the URL.\n\n The underscores are used to make the URL the same length as the original URL.\n The URL also needs to start with https and so you can use a service like\n [Serveo](https://serveo.net/) to do the https part for you. Just follow the\n instructions on the website. I recommend you to get a custom subdomain so it\n doesn't change (you can use any subdomain as long as the total url length is\n shorter than the original URL).\n\nExample:\n\nYou can run a command like: `ssh -R myserver:80:localhost:80 serveo.net`\nYou may need to setup ssh keys for the above to work (follow the given\ninstructions) This makes your url: `https://myserver.serveo.net` and then you\nwould replace the ponos url with `https://myserver.serveo.net/items/_`.\n\nInstead of using a private server, you might be able to use something like\n[mitmproxy](https://mitmproxy.org/) or [Fiddler](https://www.telerik.com/fiddler)\nto modify the server responses. This did not work for me as the game always\ncrashed (works for other requests though) but it might work for you.\n\n## Installation\n\n1. Install [Python](https://www.python.org/downloads/) >= 3.9\n\n1. Run `pip install -U tbcms`\n\n## Usage\n\n1. Run `python -m tbcms` or `py -m tbcms` depending on\n your system.\n\n1. Run `python -m tbcms --help` for more information.\n\n1. Read [jamesiotio's CITM](https://github.com/jamestiotio/CITM) on how to\n format the list of presents.\n\n1. Create a file called `presents.json` somewhere and put your presents in it.\n\n1. Run `python -m tbcms --presents path/to/presents.json` to start\n server.\n\nExample presents.json\n\n```json\n[\n {\n \"id\": 1,\n \"title\": \"Items\",\n \"body\": \"Test Body\",\n \"createdAt\": 1688648392,\n \"items\": [\n {\n \"itemId\": 22,\n \"itemCategory\": 0,\n \"amount\": 50,\n \"title\": \"Catfood\"\n },\n {\n \"itemId\": 29,\n \"itemCategory\": 0,\n \"amount\": 5,\n \"title\": \"Platinum Ticket\"\n }\n ]\n }\n]\n```\n\n## Alternative Method\n\nYou can also change the public key the game uses to verify the server responses\nto your own public key from a key pair you generated.\n\nYou can modify the `assets/nyanko-service-prd.pem` file in the APK to use your own\npublic key. You can generate a key pair using openssl:\n\n```sh\nopenssl genrsa -out private.pem 4096\nopenssl rsa -in private.pem -pubout -out public.pem\n```\n\nThe problem with this method is that you now need to intercept or use a private\nserver for every single request that uses the public key as now the game will\nreject the official server responses from PONOS.\n\nHowever, I did still manage to do all of that, but the game refused to upload\nthe save data to the game servers. It does a request to an aws server but it\naborts immediately after. I couldn't have changed the url of the server it\nuploads to to my own server because the url is from a response of another\nrequest with a signature that I don't know how to generate.\n\nAnother problem is that if you have a request with more than one slash in the\nsame place, serveo.net will respond with a 301 Moved Permanently and redirect to\nthe url with only one slash. But if the original request was a POST request,\nthe method will change to GET and break the request. If it instead used a 308\nPermanent Redirect then it would keep the method as POST and it would work.\nWhen downloading save data, PONOS accidentally has 2 slashes in the same place.\nI don't know how to fix this.\n\nI know that this is not a Flask issue because Flask responds correctly with a\n308 Permanent Redirect. I think it is a problem with serveo.net.\n\nIt's probably possible to do this method but I can't be bothered to do it.\n\nEven though this alternative method is not effective, I spent a lot of time on it\nso I wanted to include it here.\n",
"bugtrack_url": null,
"license": "",
"summary": "",
"version": "1.0.0",
"project_urls": {
"Homepage": "https://github.com/fieryhenry/tbcms"
},
"split_keywords": [],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "129b4e0255646731aeb68feb0f4b35da87ac287c6c65f05d82659e9aef539bab",
"md5": "bc0d72de745f2a33e979caebe7bc56b2",
"sha256": "8d09defc2ff1a095374cc63034d265769bb5709ee5d122b190c19b941840636f"
},
"downloads": -1,
"filename": "tbcms-1.0.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "bc0d72de745f2a33e979caebe7bc56b2",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.9",
"size": 8407,
"upload_time": "2023-08-23T08:34:39",
"upload_time_iso_8601": "2023-08-23T08:34:39.139532Z",
"url": "https://files.pythonhosted.org/packages/12/9b/4e0255646731aeb68feb0f4b35da87ac287c6c65f05d82659e9aef539bab/tbcms-1.0.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "e5711e4b94a9f5be7fc80f70f4a1d5f93580e189755dbb00f62f32a792788b0f",
"md5": "eee3e3800b8cd5b5373be217b3a40c99",
"sha256": "1d8163a5a19350ef2bbe6cc26a88b2f3535417cf921fbc4551c02ab9a2ec26b8"
},
"downloads": -1,
"filename": "tbcms-1.0.0.tar.gz",
"has_sig": false,
"md5_digest": "eee3e3800b8cd5b5373be217b3a40c99",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.9",
"size": 10470,
"upload_time": "2023-08-23T08:34:40",
"upload_time_iso_8601": "2023-08-23T08:34:40.911239Z",
"url": "https://files.pythonhosted.org/packages/e5/71/1e4b94a9f5be7fc80f70f4a1d5f93580e189755dbb00f62f32a792788b0f/tbcms-1.0.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2023-08-23 08:34:40",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "fieryhenry",
"github_project": "tbcms",
"github_not_found": true,
"lcname": "tbcms"
}