Skip to content

Commit

Permalink
fix(core): add friend source spoof
Browse files Browse the repository at this point in the history
  • Loading branch information
rhunk committed Mar 15, 2024
1 parent b06c87c commit a339e11
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 48 deletions.
1 change: 0 additions & 1 deletion common/src/main/assets/lang/en_US.json
Original file line number Diff line number Diff line change
Expand Up @@ -881,7 +881,6 @@
"spotlight": "Spotlight"
},
"add_friend_source_spoof": {
"added_by_quick_add": "By Quick Add",
"added_by_username": "By Username",
"added_by_mention": "By Mention",
"added_by_group_chat": "By Group Chat",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ class Experimental : ConfigContainer() {
requireRestart()
}
val addFriendSourceSpoof = unique("add_friend_source_spoof",
"added_by_quick_add",
"added_by_username",
"added_by_mention",
"added_by_group_chat",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,4 +173,48 @@ enum class QuotedMessageContentStatus {
JOINEDAFTERORIGINALMESSAGESENT,
UNAVAILABLE,
STORYMEDIADELETEDBYPOSTER
}

enum class FriendAddSource(
val id: Int
) {
UNKNOWN(0),
PHONE(1),
USERNAME(2),
QR_CODE(3),
ADDED_ME_BACK(4),
NEARBY(5),
SUGGESTED(6),
OFFICIAL_STORY_SEARCH(7),
DEEP_LINK(8),
INVITE(9),
STORY_CHROME(10),
SHARED_USERNAME(11),
SHARED_STORY(12),
GROUP_CHAT(13),
SHAZAM(14),
MOB(15),
FEATURED_OFFICIAL_STORY(16),
OUR_STORY(17),
INFLUENCER_RECOMMENDATION(18),
DISPLAY_NAME(198),
TEST(20),
MENTION(21),
SUBSCRIPTION(22),
MENTION_STICKER(23),
SNAPCODE_STICKER(24),
SPOTLIGHT(25),
PUBLIC_PROFILE(26),
LENS(27),
CHAT(28),
SNAP_ANYONE(29),
COMMUNITY(30),
NEARBY_FRIENDS(31),
SEARCH(32);

companion object {
fun fromId(id: Int): FriendAddSource {
return entries.firstOrNull { it.id == id } ?: UNKNOWN
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -445,7 +445,7 @@ class BulkMessagingAction : AbstractAction() {
private fun removeFriend(userId: String) {
context.mappings.useMapper(FriendRelationshipChangerMapper::class) {
val friendRelationshipChangerInstance = context.feature(AddFriendSourceSpoof::class).friendRelationshipChangerInstance!!
val removeMethod = removeFriendClass.getAsClass()?.methods?.first {
val removeMethod = friendshipRelationshipChangerKtx.getAsClass()?.methods?.first {
it.name == removeFriendMethod.getAsString()
} ?: throw Exception("Failed to find removeFriend method")

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package me.rhunk.snapenhance.core.features.impl.experiments

import me.rhunk.snapenhance.common.data.FriendAddSource
import me.rhunk.snapenhance.common.util.protobuf.ProtoEditor
import me.rhunk.snapenhance.core.event.events.impl.UnaryCallEvent
import me.rhunk.snapenhance.core.features.Feature
import me.rhunk.snapenhance.core.features.FeatureLoadParams
import me.rhunk.snapenhance.core.util.hook.HookStage
import me.rhunk.snapenhance.core.util.hook.hook
import me.rhunk.snapenhance.core.util.hook.hookConstructor
import me.rhunk.snapenhance.mapper.impl.FriendRelationshipChangerMapper

Expand All @@ -16,51 +18,50 @@ class AddFriendSourceSpoof : Feature("AddFriendSourceSpoof", loadParams = Featur
classReference.get()?.hookConstructor(HookStage.AFTER) { param ->
friendRelationshipChangerInstance = param.thisObject()
}
}

classReference.get()?.hook(addFriendMethod.get()!!, HookStage.BEFORE) { param ->
val spoofedSource = context.config.experimental.addFriendSourceSpoof.getNullable() ?: return@hook

fun setEnum(index: Int, value: String) {
val enumData = param.arg<Any>(index)
enumData::class.java.enumConstants.first { it.toString() == value }.let {
param.setArg(index, it)
context.event.subscribe(UnaryCallEvent::class) { event ->
if (event.uri != "/snapchat.friending.server.FriendAction/AddFriends") return@subscribe
val spoofedSource = context.config.experimental.addFriendSourceSpoof.getNullable() ?: return@subscribe
event.buffer = ProtoEditor(event.buffer).apply {
edit {
fun setPage(value: String) {
remove(1)
addString(1, value)
}
}

when (spoofedSource) {
"added_by_quick_add" -> {
setEnum(1, "PROFILE")
setEnum(2, "ADD_FRIENDS_BUTTON_ON_TOP_BAR_ON_FRIENDS_FEED")
setEnum(3, "ADDED_BY_SUGGESTED")
}
"added_by_group_chat" -> {
setEnum(1, "PROFILE")
setEnum(2, "GROUP_PROFILE")
setEnum(3, "ADDED_BY_GROUP_CHAT")
}
"added_by_username" -> {
setEnum(1, "SEARCH")
setEnum(2, "SEARCH")
setEnum(3, "ADDED_BY_USERNAME")
}
"added_by_qr_code" -> {
setEnum(1, "PROFILE")
setEnum(2, "PROFILE")
setEnum(3, "ADDED_BY_QR_CODE")
}
"added_by_mention" -> {
setEnum(1, "CONTEXT_CARDS")
setEnum(2, "CONTEXT_CARD")
setEnum(3, "ADDED_BY_MENTION")
}
"added_by_community" -> {
setEnum(1, "PROFILE")
setEnum(2, "PROFILE")
setEnum(3, "ADDED_BY_COMMUNITY")
editEach(2) {
remove(3) // remove suggestion token
fun setSource(source: FriendAddSource) {
remove(2)
addVarInt(2, source.id)
}

when (spoofedSource) {
"added_by_group_chat" -> {
setPage("group_profile")
setSource(FriendAddSource.GROUP_CHAT)
}
"added_by_username" -> {
setPage("search")
setSource(FriendAddSource.USERNAME)
}
"added_by_qr_code" -> {
setPage("scan_snapcode")
setSource(FriendAddSource.QR_CODE)
}
"added_by_mention" -> {
setPage("context_card")
setSource(FriendAddSource.MENTION)
}
"added_by_community" -> {
setPage("profile")
setSource(FriendAddSource.COMMUNITY)
}
}
}
else -> return@hook
}
}
}.toByteArray()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import java.lang.reflect.Modifier

class FriendRelationshipChangerMapper : AbstractClassMapper("FriendRelationshipChanger") {
val classReference = classReference("class")
val addFriendMethod = string("addFriendMethod")

val removeFriendClass = classReference("removeFriendClass")
val friendshipRelationshipChangerKtx = classReference("removeFriendClass")
val addFriendMethod = string("addFriendMethod")
val removeFriendMethod = string("removeFriendMethod")

init {
Expand All @@ -28,7 +28,6 @@ class FriendRelationshipChangerMapper : AbstractClassMapper("FriendRelationshipC

this@FriendRelationshipChangerMapper.apply {
classReference.set(classDef.getClassName())
addFriendMethod.set(addFriendDexMethod.name)
}

return@mapper
Expand All @@ -45,8 +44,19 @@ class FriendRelationshipChangerMapper : AbstractClassMapper("FriendRelationshipC
getClass(it.parameterTypes[3])?.getClassName()?.endsWith("InteractionPlacementInfo") == true
} ?: continue

removeFriendClass.set(classDef.getClassName())
friendshipRelationshipChangerKtx.set(classDef.getClassName())
removeFriendMethod.set(removeFriendDexMethod.name)

val addFriendDexMethod = classDef.methods.firstOrNull {
Modifier.isStatic(it.accessFlags) &&
it.parameterTypes.size == 5 &&
it.parameterTypes[1] == "Ljava/lang/String;" &&
getClass(it.parameterTypes[2])?.isEnum() == true &&
getClass(it.parameterTypes[4])?.isEnum() == true &&
it.parameterTypes[5] == "I"
} ?: return@mapper

addFriendMethod.set(addFriendDexMethod.name)
return@mapper
}
}
Expand Down

0 comments on commit a339e11

Please sign in to comment.