mirror of
https://github.com/whitechi73/OpenShamrock.git
synced 2024-08-14 13:12:17 +08:00
Shamrock
: fix #236
This commit is contained in:
parent
63ce2d40bd
commit
3b210d7ed0
@ -0,0 +1,29 @@
|
|||||||
|
package com.tencent.mobileqq.perf.block;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import epic.EIPCClient;
|
||||||
|
import epic.EIPCResult;
|
||||||
|
import kotlin.Metadata;
|
||||||
|
import kotlin.jvm.JvmStatic;
|
||||||
|
|
||||||
|
public final class BinderMethodProxy {
|
||||||
|
@NotNull
|
||||||
|
public static final BinderMethodProxy INSTANCE;
|
||||||
|
|
||||||
|
static {
|
||||||
|
INSTANCE = new BinderMethodProxy();
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
public static EIPCResult callServer(@NotNull EIPCClient client, @Nullable String module, @Nullable String action, @Nullable Bundle bundle) {
|
||||||
|
//MainBlockMethodMonitor.onMethodStart();
|
||||||
|
//EIPCResult callServer = client.callServer(str, str2, bundle);
|
||||||
|
//MainBlockMethodMonitor.onMethodEnd();
|
||||||
|
//return callServer;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
package com.tencent.mobileqq.qipc;
|
||||||
|
|
||||||
|
import epic.EIPCClient;
|
||||||
|
|
||||||
|
public class QIPCClientHelper {
|
||||||
|
public static synchronized QIPCClientHelper getInstance() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EIPCClient getClient() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
package com.tencent.mobileqq.qmmkv;
|
||||||
|
|
||||||
|
public class MMKVOptionEntity {
|
||||||
|
public String decodeString(String str, String str2) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
package com.tencent.mobileqq.qmmkv;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
public class QMMKV {
|
||||||
|
public static MMKVOptionEntity from(Context context, String str) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
package com.tencent.mobileqq.transfile.dns;
|
||||||
|
|
||||||
|
import android.os.Parcel;
|
||||||
|
import android.os.Parcelable;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
public class IpData implements Parcelable {
|
||||||
|
public int mFailedCount;
|
||||||
|
public String mIp;
|
||||||
|
public int mPort;
|
||||||
|
public int mType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Describe the kinds of special objects contained in this Parcelable
|
||||||
|
* instance's marshaled representation. For example, if the object will
|
||||||
|
* include a file descriptor in the output of {@link #writeToParcel(Parcel, int)},
|
||||||
|
* the return value of this method must include the
|
||||||
|
* {@link #CONTENTS_FILE_DESCRIPTOR} bit.
|
||||||
|
*
|
||||||
|
* @return a bitmask indicating the set of special object types marshaled
|
||||||
|
* by this Parcelable object instance.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int describeContents() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flatten this object in to a Parcel.
|
||||||
|
*
|
||||||
|
* @param dest The Parcel in which the object should be written.
|
||||||
|
* @param flags Additional flags about how the object should be written.
|
||||||
|
* May be 0 or {@link #PARCELABLE_WRITE_RETURN_VALUE}.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void writeToParcel(@NonNull Parcel dest, int flags) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
4
qqinterface/src/main/java/epic/EIPCClient.java
Normal file
4
qqinterface/src/main/java/epic/EIPCClient.java
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
package epic;
|
||||||
|
|
||||||
|
public class EIPCClient {
|
||||||
|
}
|
11
qqinterface/src/main/java/epic/EIPCResult.java
Normal file
11
qqinterface/src/main/java/epic/EIPCResult.java
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
package epic;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
public class EIPCResult {
|
||||||
|
public Bundle data;
|
||||||
|
|
||||||
|
public boolean isSuccess() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
package moe.fuqiuluo.qqinterface.servlet.msg.convert
|
package moe.fuqiuluo.qqinterface.servlet.msg.convert
|
||||||
|
|
||||||
|
import com.tencent.mobileqq.qmmkv.QMMKV
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.MsgConstant
|
import com.tencent.qqnt.kernel.nativeinterface.MsgConstant
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.MsgElement
|
import com.tencent.qqnt.kernel.nativeinterface.MsgElement
|
||||||
import moe.fuqiuluo.qqinterface.servlet.transfile.RichProtoSvc
|
import moe.fuqiuluo.qqinterface.servlet.transfile.RichProtoSvc
|
||||||
@ -13,6 +14,8 @@ import moe.fuqiuluo.shamrock.helper.db.MessageDB
|
|||||||
import moe.fuqiuluo.shamrock.tools.asJsonObject
|
import moe.fuqiuluo.shamrock.tools.asJsonObject
|
||||||
import moe.fuqiuluo.shamrock.tools.asString
|
import moe.fuqiuluo.shamrock.tools.asString
|
||||||
import moe.fuqiuluo.shamrock.tools.json
|
import moe.fuqiuluo.shamrock.tools.json
|
||||||
|
import mqq.app.MobileQQ
|
||||||
|
import kotlin.jvm.internal.Intrinsics
|
||||||
|
|
||||||
internal sealed class MessageElemConverter: IMessageConvert {
|
internal sealed class MessageElemConverter: IMessageConvert {
|
||||||
/**
|
/**
|
||||||
@ -135,14 +138,16 @@ internal sealed class MessageElemConverter: IMessageConvert {
|
|||||||
ImageMapping(md5.uppercase(), chatType, image.fileSize)
|
ImageMapping(md5.uppercase(), chatType, image.fileSize)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
//LogCenter.log(image.toString())
|
||||||
|
|
||||||
return MessageSegment(
|
return MessageSegment(
|
||||||
type = "image",
|
type = "image",
|
||||||
data = hashMapOf(
|
data = hashMapOf(
|
||||||
"file" to md5,
|
"file" to md5,
|
||||||
"url" to when(chatType) {
|
"url" to when(chatType) {
|
||||||
MsgConstant.KCHATTYPEGROUP -> RichProtoSvc.getGroupPicDownUrl(md5)
|
MsgConstant.KCHATTYPEDISC, MsgConstant.KCHATTYPEGROUP -> RichProtoSvc.getGroupPicDownUrl(image.originImageUrl, md5)
|
||||||
MsgConstant.KCHATTYPEC2C -> RichProtoSvc.getC2CPicDownUrl(md5)
|
MsgConstant.KCHATTYPEC2C -> RichProtoSvc.getC2CPicDownUrl(image.originImageUrl, md5)
|
||||||
MsgConstant.KCHATTYPEGUILD -> RichProtoSvc.getGuildPicDownUrl(md5)
|
MsgConstant.KCHATTYPEGUILD -> RichProtoSvc.getGuildPicDownUrl(image.originImageUrl, md5)
|
||||||
else -> unknownChatType(chatType)
|
else -> unknownChatType(chatType)
|
||||||
},
|
},
|
||||||
"subType" to image.picSubType,
|
"subType" to image.picSubType,
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
@file:OptIn(ExperimentalSerializationApi::class)
|
@file:OptIn(ExperimentalSerializationApi::class)
|
||||||
package moe.fuqiuluo.qqinterface.servlet.transfile
|
package moe.fuqiuluo.qqinterface.servlet.transfile
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
import com.tencent.mobileqq.pb.ByteStringMicro
|
import com.tencent.mobileqq.pb.ByteStringMicro
|
||||||
|
import com.tencent.mobileqq.perf.block.BinderMethodProxy
|
||||||
|
import com.tencent.mobileqq.qipc.QIPCClientHelper
|
||||||
import com.tencent.mobileqq.transfile.FileMsg
|
import com.tencent.mobileqq.transfile.FileMsg
|
||||||
import com.tencent.mobileqq.transfile.api.IProtoReqManager
|
import com.tencent.mobileqq.transfile.api.IProtoReqManager
|
||||||
|
import com.tencent.mobileqq.transfile.dns.IpData
|
||||||
import com.tencent.mobileqq.transfile.protohandler.RichProto
|
import com.tencent.mobileqq.transfile.protohandler.RichProto
|
||||||
import com.tencent.mobileqq.transfile.protohandler.RichProtoProc
|
import com.tencent.mobileqq.transfile.protohandler.RichProtoProc
|
||||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||||
@ -19,18 +23,35 @@ import moe.fuqiuluo.shamrock.tools.slice
|
|||||||
import moe.fuqiuluo.shamrock.tools.toHexString
|
import moe.fuqiuluo.shamrock.tools.toHexString
|
||||||
import moe.fuqiuluo.shamrock.utils.PlatformUtils
|
import moe.fuqiuluo.shamrock.utils.PlatformUtils
|
||||||
import moe.fuqiuluo.shamrock.xposed.helper.AppRuntimeFetcher
|
import moe.fuqiuluo.shamrock.xposed.helper.AppRuntimeFetcher
|
||||||
|
import mqq.app.MobileQQ
|
||||||
import protobuf.oidb.cmd0xfc2.Oidb0xfc2ChannelInfo
|
import protobuf.oidb.cmd0xfc2.Oidb0xfc2ChannelInfo
|
||||||
import protobuf.oidb.cmd0xfc2.Oidb0xfc2MsgApplyDownloadReq
|
import protobuf.oidb.cmd0xfc2.Oidb0xfc2MsgApplyDownloadReq
|
||||||
import protobuf.oidb.cmd0xfc2.Oidb0xfc2ReqBody
|
import protobuf.oidb.cmd0xfc2.Oidb0xfc2ReqBody
|
||||||
import protobuf.oidb.cmd0xfc2.Oidb0xfc2RspBody
|
import protobuf.oidb.cmd0xfc2.Oidb0xfc2RspBody
|
||||||
import mqq.app.MobileQQ
|
|
||||||
import tencent.im.cs.cmd0x346.cmd0x346
|
import tencent.im.cs.cmd0x346.cmd0x346
|
||||||
import tencent.im.oidb.cmd0x6d6.oidb_0x6d6
|
import tencent.im.oidb.cmd0x6d6.oidb_0x6d6
|
||||||
import tencent.im.oidb.cmd0xe37.cmd0xe37
|
import tencent.im.oidb.cmd0xe37.cmd0xe37
|
||||||
import tencent.im.oidb.oidb_sso
|
import tencent.im.oidb.oidb_sso
|
||||||
|
import java.util.ArrayList
|
||||||
import kotlin.coroutines.resume
|
import kotlin.coroutines.resume
|
||||||
|
|
||||||
|
private const val GPRO_PIC = "gchat.qpic.cn"
|
||||||
|
private const val GPRO_PIC_NT = "multimedia.nt.qq.com.cn"
|
||||||
|
private const val C2C_PIC = "c2cpicdw.qpic.cn"
|
||||||
|
|
||||||
internal object RichProtoSvc: BaseSvc() {
|
internal object RichProtoSvc: BaseSvc() {
|
||||||
|
/*@Deprecated("Use RichProtoSvc.getQQDns instead", ReplaceWith("getQQDns(domain)"))
|
||||||
|
fun getQQDns(domain: String) {
|
||||||
|
val bundle = Bundle()
|
||||||
|
bundle.putString("domain", "xxx")
|
||||||
|
bundle.putInt("businessType", 1)
|
||||||
|
val result = BinderMethodProxy
|
||||||
|
.callServer(QIPCClientHelper.getInstance().client, "InnerDnsModule", "reqDomain2IpList", bundle)
|
||||||
|
if (result.isSuccess) {
|
||||||
|
val ipList: ArrayList<IpData> = result.data.getParcelableArrayList("ip")!!
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
suspend fun getGuildFileDownUrl(peerId: String, channelId: String, fileId: String, bizId: Int): String {
|
suspend fun getGuildFileDownUrl(peerId: String, channelId: String, fileId: String, bizId: Int): String {
|
||||||
val buffer = sendOidbAW("OidbSvcTrpcTcp.0xfc2_0", 4034, 0, ProtoBuf.encodeToByteArray(
|
val buffer = sendOidbAW("OidbSvcTrpcTcp.0xfc2_0", 4034, 0, ProtoBuf.encodeToByteArray(
|
||||||
Oidb0xfc2ReqBody(
|
Oidb0xfc2ReqBody(
|
||||||
@ -142,19 +163,35 @@ internal object RichProtoSvc: BaseSvc() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun getGroupPicDownUrl(
|
fun getGroupPicDownUrl(
|
||||||
|
originalUrl: String,
|
||||||
md5: String
|
md5: String
|
||||||
): String {
|
): String {
|
||||||
return "http://gchat.qpic.cn/gchatpic_new/0/0-0-${md5.uppercase()}/0?term=2"
|
val domain = if (originalUrl.contains("rkey=")) GPRO_PIC_NT else GPRO_PIC
|
||||||
|
if (originalUrl.isNotEmpty()) {
|
||||||
|
return "https://$domain$originalUrl"
|
||||||
|
}
|
||||||
|
return "https://$domain/gchatpic_new/0/0-0-${md5.uppercase()}/0?term=2"
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getC2CPicDownUrl(
|
fun getC2CPicDownUrl(
|
||||||
|
originalUrl: String,
|
||||||
md5: String
|
md5: String
|
||||||
): String {
|
): String {
|
||||||
return "https://c2cpicdw.qpic.cn/offpic_new/0/123-0-${md5.uppercase()}/0?term=2"
|
if (originalUrl.isNotEmpty()) {
|
||||||
|
return "https://$C2C_PIC$originalUrl"
|
||||||
|
}
|
||||||
|
return "https://$C2C_PIC/offpic_new/0/123-0-${md5.uppercase()}/0?term=2"
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getGuildPicDownUrl(md5: String): String {
|
fun getGuildPicDownUrl(
|
||||||
return "https://gchat.qpic.cn/qmeetpic/0/0-0-${md5.uppercase()}/0?term=2"
|
originalUrl: String,
|
||||||
|
md5: String
|
||||||
|
): String {
|
||||||
|
val domain = if (originalUrl.contains("rkey=")) GPRO_PIC_NT else GPRO_PIC
|
||||||
|
if (originalUrl.isNotEmpty()) {
|
||||||
|
return "https://$domain$originalUrl"
|
||||||
|
}
|
||||||
|
return "https://$domain/qmeetpic/0/0-0-${md5.uppercase()}/0?term=2"
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getC2CVideoDownUrl(
|
suspend fun getC2CVideoDownUrl(
|
||||||
@ -321,12 +358,4 @@ internal object RichProtoSvc: BaseSvc() {
|
|||||||
RichProtoProc.procRichProtoReq(richProtoReq)
|
RichProtoProc.procRichProtoReq(richProtoReq)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getGuildPttDownUrl(
|
|
||||||
peerId: String,
|
|
||||||
md5Hex: String,
|
|
||||||
fileUUId: String
|
|
||||||
): String {
|
|
||||||
return "unsupported"
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -35,8 +35,8 @@ internal object GetImage: IActionHandler() {
|
|||||||
image.size,
|
image.size,
|
||||||
image.fileName,
|
image.fileName,
|
||||||
when(image.chatType) {
|
when(image.chatType) {
|
||||||
MsgConstant.KCHATTYPEGROUP -> RichProtoSvc.getGroupPicDownUrl(fileMd5)
|
MsgConstant.KCHATTYPEGROUP -> RichProtoSvc.getGroupPicDownUrl("", fileMd5)
|
||||||
MsgConstant.KCHATTYPEC2C -> RichProtoSvc.getC2CPicDownUrl(fileMd5)
|
MsgConstant.KCHATTYPEC2C -> RichProtoSvc.getC2CPicDownUrl("", fileMd5)
|
||||||
else -> error("Not supported chat type: ${image.chatType}, convertMsgElementsToMsgSegment::Pic")
|
else -> error("Not supported chat type: ${image.chatType}, convertMsgElementsToMsgSegment::Pic")
|
||||||
}
|
}
|
||||||
), echo = echo)
|
), echo = echo)
|
||||||
|
@ -103,7 +103,7 @@ internal object UploadGroupFile : IActionHandler() {
|
|||||||
|
|
||||||
// 根据文件大小调整超时时间
|
// 根据文件大小调整超时时间
|
||||||
val msgIdPair = MessageHelper.generateMsgId(MsgConstant.KCHATTYPEGROUP)
|
val msgIdPair = MessageHelper.generateMsgId(MsgConstant.KCHATTYPEGROUP)
|
||||||
val info = (withTimeoutOrNull((srcFile.length() / (300 * 1024)) * 1000 + 5000) {
|
val info = (withTimeoutOrNull((srcFile.length() / (125 * 1024)) * 1000 + 5000) {
|
||||||
val msgService = QRoute.api(IMsgService::class.java)
|
val msgService = QRoute.api(IMsgService::class.java)
|
||||||
val contact = MessageHelper.generateContact(MsgConstant.KCHATTYPEGROUP, groupId)
|
val contact = MessageHelper.generateContact(MsgConstant.KCHATTYPEGROUP, groupId)
|
||||||
suspendCancellableCoroutine<FileTransNotifyInfo?> {
|
suspendCancellableCoroutine<FileTransNotifyInfo?> {
|
||||||
|
@ -1,12 +1,42 @@
|
|||||||
|
@file:Suppress("UNUSED_VARIABLE", "LocalVariableName")
|
||||||
|
|
||||||
package moe.fuqiuluo.shamrock.xposed.hooks
|
package moe.fuqiuluo.shamrock.xposed.hooks
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import com.tencent.mobileqq.perf.block.BinderMethodProxy
|
||||||
|
import com.tencent.mobileqq.qmmkv.MMKVOptionEntity
|
||||||
|
import de.robv.android.xposed.XposedBridge
|
||||||
|
import epic.EIPCClient
|
||||||
|
import moe.fuqiuluo.shamrock.helper.LogCenter
|
||||||
|
import moe.fuqiuluo.shamrock.tools.beforeHook
|
||||||
|
import moe.fuqiuluo.shamrock.tools.hookMethod
|
||||||
|
import moe.fuqiuluo.shamrock.xposed.loader.LuoClassloader
|
||||||
|
import moe.fuqiuluo.symbols.Process
|
||||||
import moe.fuqiuluo.symbols.XposedHook
|
import moe.fuqiuluo.symbols.XposedHook
|
||||||
|
import java.lang.reflect.Modifier
|
||||||
|
|
||||||
@XposedHook(priority = -1)
|
@XposedHook(priority = -1, process = Process.ALL)
|
||||||
internal class HookForDebug: IAction {
|
internal class HookForDebug: IAction {
|
||||||
override fun invoke(ctx: Context) {
|
override fun invoke(ctx: Context) {
|
||||||
/*
|
/*val NtDnsManager = LuoClassloader.load("com.tencent.qqnt.dns.NtDnsManager")!!
|
||||||
|
val NtDnsInternal = NtDnsManager.declaredMethods.first {
|
||||||
|
!Modifier.isStatic(it.modifiers) && it.parameterCount == 0
|
||||||
|
}.returnType
|
||||||
|
XposedBridge.hookMethod(NtDnsInternal.declaredMethods.first {
|
||||||
|
it.parameterCount == 2
|
||||||
|
&& it.parameterTypes[0] == String::class.java
|
||||||
|
&& it.parameterTypes[1] == Int::class.java
|
||||||
|
&& it.returnType == ArrayList::class.java
|
||||||
|
}, beforeHook {
|
||||||
|
val domain = it.args[0] as String
|
||||||
|
val type = it.args[1] as Int
|
||||||
|
LogCenter.log("NtDnsManager: reqDomain2IpList($domain, $type)")
|
||||||
|
LogCenter.log(Exception().stackTraceToString())
|
||||||
|
})*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
val httpEngineService = AppRuntimeFetcher.appRuntime
|
val httpEngineService = AppRuntimeFetcher.appRuntime
|
||||||
.getRuntimeService(IHttpEngineService::class.java, "all")
|
.getRuntimeService(IHttpEngineService::class.java, "all")
|
||||||
httpEngineService.javaClass.hookMethod("sendReq").before {
|
httpEngineService.javaClass.hookMethod("sendReq").before {
|
||||||
@ -19,7 +49,17 @@ internal class HookForDebug: IAction {
|
|||||||
LogCenter.log("请求地址: ${req.mReqUrl}")
|
LogCenter.log("请求地址: ${req.mReqUrl}")
|
||||||
LogCenter.log("请求: ${req.toInnerValuesString(NetReq::class.java)}")
|
LogCenter.log("请求: ${req.toInnerValuesString(NetReq::class.java)}")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
BinderMethodProxy::class.java.hookMethod("callServer").before {
|
||||||
|
val action = it.args[2] as String
|
||||||
|
if (action == "reqDomain2IpList") {
|
||||||
|
LogCenter.log(Exception().stackTraceToString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EIPCClient::class.java.hookMethod("callServer").before {
|
||||||
|
val module = it.args[0] as String
|
||||||
|
val action = it.args[1] as String
|
||||||
|
if (action == "reqDomain2IpList" || module.contains("dns", ignoreCase = true)) {
|
||||||
|
LogCenter.log(Exception().stackTraceToString())
|
||||||
|
}
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user