Comments (24)
It appears that BeReal stepped up their protection against reverse engineering, it now seems to detect HTTPToolkit on a rooted phone.
Using https://modules.lsposed.org/module/io.github.tehcneko.sslunpinning works and dumps the requests. I'll post them here tomorrow
from befake.
Seems like they started cert pinning in the iOS app so I was unable to research anything. I might archive this project as i don't have access to an Android device or a jailbroken iOS device.
from befake.
Here are the post upload requests and responses. I forgot to update the app tho, I'll check tomorrow if there's any differences between version 0.61.7 and 0.63.4.
Individual photo upload
Headers
cache-control: public,max-age=172800
connection: Keep-Alive
content-length: 100862
content-type: image/webp
host: storage.googleapis.com
x-goog-content-length-range: 1024,1048576
PUT
https://storage.googleapis.com/storage.bere.al/Photos/userid/post/test-test.webp?X-Goog-Algorithm=GOOG4-RSA-SHA256&X-Goog-Credential=prod-backend-fasterstore%40alexisbarreyat-bereal.iam.gserviceaccount.com%2F20230219%2Fauto%2Fstorage%2Fgoog4_request&X-Goog-Date=20230219T215032Z&X-Goog-Expires=172801&X-Goog-SignedHeaders=cache-control%3Bcontent-type%3Bhost%3Bx-goog-content-length-range&X-Goog-Signature=signature
post upload, url https://mobile.bereal.com/api/content/posts
Headers:
accept-encoding: gzip
authorization: Bearer key
bereal-app-language: fr
bereal-app-version: 0.61.7
bereal-device-id: deviceid
bereal-device-language: fr
bereal-os-version: 8.1.0
bereal-platform: android
bereal-timezone: Europe/Paris
connection: Keep-Alive
content-length: 445
content-type: application/json; charset=utf-8
host: mobile.bereal.com
user-agent: okhttp/4.10.0
x-datadog-origin: rum
x-datadog-parent-id: 12345678910
x-datadog-sampled: 1
x-datadog-sampling-priority: 1
x-datadog-trace-id: 12345678910
POST content:
{
"frontCamera": {
"bucket": "storage.bere.al",
"path": "Photos/userid/post/test-test.webp",
"width": 1500,
"height": 2000
},
"backCamera": {
"bucket": "storage.bere.al",
"path": "Photos/userid/post/test2-test2.webp",
"width": 1500,
"height": 2000
},
"takenAt": "2023-02-19T21:28:43.367Z",
"isLate": true,
"visibility": [
"friends-of-friends"
],
"retakeCounter": 0,
"location": {
"longitude": xx,
"latitude": xx
}
}
Response:
{
"user": {
"id": "userid",
"username": "username",
"profilePicture": {
"height": 500,
"width": 500,
"url": "https://cdn.bereal.network/Photos/userid/profile/userid-unixtimestamp-profile-picture.jpg"
}
},
"primary": {
"height": 2000,
"width": 1500,
"url": "https://cdn.bereal.network/Photos/userid/post/picture1.webp"
},
"secondary": {
"height": 2000,
"width": 1500,
"url": "https://cdn.bereal.network/Photos/userid/post/picture2.webp"
},
"isLate": true,
"lateInSeconds": seconds late,
"moment": {
"id": "moment-id",
"region": "europe-west"
},
"id": "post id?",
"location": {
"longitude": xx,
"latitude": xx
},
"caption": null,
"retakeCounter": 0,
"comments": {
"sample": [],
"total": 0
},
"realmojis": {
"sample": [],
"total": 0
},
"screenshots": {
"sample": [],
"total": 0
},
"createdAt": "same date format as before",
"takenAt": "same date format as before",
"visibility": [
"friends",
"friends-of-friends"
],
"canDelete": true
}
Edit: I'm using a Nexus 5X running LineageOS 15.1 with latest magisk, zygisk LSPosed and the certificate unpinner above if you want to reproduce that.
from befake.
I have some really bad news: the login process has gotten even more complicated, with the use of SafetyNet and other google stuff. Can someone with access to a jailbroken IOS device dump the login endpoints to see if they can be used by this library?
from befake.
Uh I just tried logging in using the master branch and it just works?? Maybe someone using an Iphone can dump the newest user-agents and iOS receipt.
from befake.
Btw is anyone planning on creating a GTK4 frontend using this library? I just recently got a Pinephone Pro and having BeReal on it would be awesome π
from befake.
I don't have time nowadays but when I get a second i will download the latest TestFlight version and try to reverse engineer the API againπ¬
from befake.
Seems like i will be able to do it tomorrow since I've fallen sick.
from befake.
Edit: I've discovered the endpoint to generate the picture upload API. Gonna add it to my private fork and make a pull request soon.
from befake.
I think I posted pythonic code for Signed picture uploads earlier if you would like to take a look
from befake.
In the code, Post
class is not instantiated
from befake.
Yeah program does not work at all, completely unusable
from befake.
any updates on this?
from befake.
Ok thanks @notmarek π¬
from befake.
@notmarek good to know, as I said some comments before, the problem seems to be with the Post class, I think the apis were not changed because I posted something with another website, I cannot give you more info since it happened some months ago.
from befake.
There has been a fix for uploading as well as the login captcha already on a fork
from befake.
@notmarek In the past I was able to monitor requests using android studio emulator and this project: https://github.com/shroudedcode/apk-mitm
But it didn't work the last time I used it, probably because of a stupid mistake I made, I currently don't have enough time to investigate...
from befake.
@h7ndrx What fork is it?
from befake.
They
Seems like they started cert pinning in the iOS app so I was unable to research anything. I might archive this project as i don't have access to an Android device or a jailbroken iOS device.
You can use AVD on android studio and root using https://github.com/newbit1/rootAVD and unpin the ssl then proxy straight to your computer.
The new post code was first found by hubertoschusch I believe in this playground.
Logging in has also been bypassed by Rvaidan, I believe he is using google cloud functions as a proxy generator or something like that. However when I use mitm to proxy login requests, its still dependent on different Certs from ios and android so Im quite unsure how he is bypassing the recaptcha.
Bereal is definitely stepping up
Heres my pythonic version of the posting that matches this project somewhat:
@app.route("/signedpostinstant/<token>/<uid>/", methods=["POST"])
@app.route("/signedpostinstant/<token>/<uid>/<caption>", methods=["POST"])
def signedpostinstant(token:str, uid:str, caption:str=''):
#==============================================================================================
print(request.form.to_dict())
print(request.files)
print(caption)
#==============================================================================================
ispublic = json.loads(request.form.to_dict()['public'].lower())
latitude = request.form.to_dict()['latitude']
longitude = request.form.to_dict()['longitude']
haslocation = json.loads(request.form.to_dict()['haslocation'].lower())
print(ispublic, type(ispublic))
print(latitude, type(latitude))
print(longitude, type(longitude))
print(haslocation, type(haslocation))
#file manipulation
def get_data(version):
version_data = io.BytesIO()
version.save(version_data, format="JPEG", quality=90)
version_data = version_data.getvalue()
return version_data
def extension(img):
mime_type = Image.MIME[img.format]
if mime_type != "image/jpeg":
if not img.mode == "RGB":
img = img.convert("RGB")
return img
p = request.files['primary']
primary = Image.open(io.BytesIO(p.read()))
primary = extension(primary)
prim_data = get_data(primary) #this is the primary image file
primarysize = str(len(prim_data))
s = request.files['secondary']
secondary = Image.open(io.BytesIO(s.read()))
secondary = extension(secondary)
sec_data = get_data(secondary) #this is the secondary image file
secondarysize = str(len(sec_data))
#==============================================================================================
apiurl = f"https://mobile.bereal.com/api/content/posts/upload-url?mimeType=image%2Fwebp"
headers = {
"authorization": "Bearer {}".format(token),
"accept-encoding": "gzip",
"user-agent": "okhttp/4.10.0",
"if-none-match": 'W/"507-M16WxEgA1LffRgMAGSRIlonfNV8"'
}
signed_upload_res = requests.get(url=apiurl, headers=headers)
print("----- SIGNED UPLOAD -----")
print(signed_upload_res)
print(signed_upload_res.json())
if signed_upload_res.status_code != 200: return signed_upload_res.json()
print('----- END -----')
signed_upload_res = signed_upload_res.json()
signed_upload_res = signed_upload_res["data"]
prim_path = signed_upload_res[0]["path"]
sec_path = signed_upload_res[1]["path"]
def intostorage(signed_res, file):
bucket = signed_res['bucket']
expires = signed_res['expireAt']
image_path = signed_res['path']
bucket_headers = signed_res['headers']
bucket_url = signed_res['url']
print("----- BUCKET INFO -----")
print(bucket, "\n >>>>")
print(expires, "\n >>>>")
print(image_path, "\n >>>>")
print(bucket_headers, "\n >>>>")
print(bucket_url, "\n >>>>")
print('----- END -----')
ret = requests.put(url=bucket_url, headers=bucket_headers, data=file)
print("----- BUCKET PUT RESP -----")
print(ret)
print(ret.text)
print('----- END -----')
if ret.status_code != 200: raise Exception(f"Error uploading image: {ret.status_code}, {ret.text}")
return ret
prim_bucket_ret = intostorage(signed_upload_res[0] ,prim_data)
sec_bucket_ret = intostorage(signed_upload_res[1] ,sec_data)
print("----- BUCKET RET -----")
print(prim_bucket_ret)
print(">>>>>")
print(sec_bucket_ret)
print('----- END -----')
now = pendulum.now()
taken_at = f"{now.to_date_string()}T{now.to_time_string()}Z"
payload = {
"isPublic": ispublic,
"isLate": False,
"retakeCounter": 0,
"takenAt": taken_at,
#"location": location,
"caption": caption,
"backCamera": {
"bucket": "storage.bere.al",
"height": 2000,
"width": 1500,
"path": prim_path,
},
"frontCamera": {
"bucket": "storage.bere.al",
"height": 2000,
"width": 1500,
"path": sec_path,
},
}
if haslocation: payload["location"] = {"latitude": latitude,"longitude": longitude,}
complete_res = requests.post(url=api_url+'/content/post',json=payload,headers={"content-type" : "application/json", "authorization": token},)
print(complete_res)
print(complete_res.json())
return complete_res.json()
from befake.
Maybe throwing the BeReal APK into https://www.decompiler.com/ gives enough insight for reverse-engineering? I've made some good experiences with that approach.
from befake.
Thank you @VxlerieUwU
from befake.
@VxlerieUwU any idea of how to fix the login ? :)
from befake.
I'll investigate and post some endpoints here soon this week. I think BeReal is making their platform much secure and harder to reverse engineer, we'll have to dump the api endpoints whenever a new update goes public.
from befake.
Btw the Picture class here needs to be completely rewritten, uploads are now for both primary and secondary image at the same time, and at a seperate endpoint for Realmojis.
from befake.
Related Issues (20)
- Please STOP modifying the codes directly on the master branche before testing it HOT 1
- Friends download results in file cluster HOT 3
- a couple be real HOT 3
- the authentication endpoint no longer works HOT 2
- Assertion error while calling bf.post_realmoji
- Connection duration
- Enhancement: Second and third memory HOT 3
- Phone Number Formating Clarity. HOT 2
- sessionInfo error during login before verification
- Tutorial? HOT 1
- Can't share a bereal (upload a picture to the servers) HOT 10
- Can't Login HOT 9
- AttributeError: 'str' object has no attribute 'write' HOT 5
- Add support for extra bereals HOT 5
- Receiving Bad Request 400 response when refreshing token HOT 2
- Add releases / version numbers HOT 1
- bereal token expiring after a day HOT 2
- Link GitHub Packages to Repositroy
- Error on login: `'BeFake' object has no attribute 'refresh_token'` HOT 12
- KeyError: 'notification_id' HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. πππ
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google β€οΈ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from befake.