Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public ReverseEventCountStruct() { }
public int BotLogEventCount = 0;
public int BotMessageEventCount = 0;
public int BotNewDeviceVerifyEventCount = 0;
public int BotOfflineEventCount = 0;
public int BotOnlineEventCount = 0;
public int BotQrCodeEventCount = 0;
public int BotQrCodeQueryEventCount = 0;
Expand Down
39 changes: 39 additions & 0 deletions Lagrange.Core.NativeAPI/LoginEntryPoint.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using System.Runtime.InteropServices;
using System.Text;
using Lagrange.Core.Common.Interface;
using Lagrange.Core.NativeAPI.NativeModel.Common;

namespace Lagrange.Core.NativeAPI
{
public static class LoginEntryPoint
{
[UnmanagedCallersOnly(EntryPoint = "SubmitCaptcha")]
public static bool SubmitCaptcha(int index, ByteArrayNative ticket, ByteArrayNative randStr)
{
if (Program.Contexts.Count <= index)
{
return false;
}

var ticketData = ticket.ToByteArrayWithoutFree();
var randStrData = randStr.ToByteArrayWithoutFree();

BotContext context = Program.Contexts[index].BotContext;
return context.SubmitCaptcha(Encoding.UTF8.GetString(ticketData), Encoding.UTF8.GetString(randStrData));
}

[UnmanagedCallersOnly(EntryPoint = "SubmitSMSCode")]
public static bool SubmitSMSCode(int index, ByteArrayNative code)
{
if (Program.Contexts.Count <= index)
{
return false;
}

var codeData = code.ToByteArrayWithoutFree();

BotContext context = Program.Contexts[index].BotContext;
return context.SubmitSMSCode(Encoding.UTF8.GetString(codeData));
}
};
};
11 changes: 7 additions & 4 deletions Lagrange.Core.NativeAPI/NativeModel/Common/BotKeystoreStruct.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ namespace Lagrange.Core.NativeAPI.NativeModel.Common
{
public struct BotKeystoreStruct
{
public BotKeystoreStruct() { }
public BotKeystoreStruct()
{ }

public long Uin = 0;

Expand Down Expand Up @@ -105,7 +106,8 @@ public static implicit operator BotKeystoreStruct(BotKeystore keystore)
{
bytePsKey[i++] = new ByteArrayKVPNative
{
Key = Encoding.UTF8.GetBytes(kvp.Key), Value = Encoding.UTF8.GetBytes(kvp.Value)
Key = Encoding.UTF8.GetBytes(kvp.Key),
Value = Encoding.UTF8.GetBytes(kvp.Value)
};
}

Expand Down Expand Up @@ -143,7 +145,8 @@ public BotKeystore ToKeystoreWithoutFree()
var psKey = new Dictionary<string, string>();
foreach (var kvp in (ByteArrayKVPNative[])PsKey)
{
psKey[Encoding.UTF8.GetString(kvp.Key)] = Encoding.UTF8.GetString(kvp.Value);
// psKey[Encoding.UTF8.GetString(kvp.Key)] = Encoding.UTF8.GetString(kvp.Value); Oh shit, are u okay?
psKey[Encoding.UTF8.GetString(kvp.Key.ToByteArrayWithoutFree())] = Encoding.UTF8.GetString(kvp.Value.ToByteArrayWithoutFree());
}

return new BotKeystore()
Expand Down Expand Up @@ -178,4 +181,4 @@ public BotKeystore ToKeystoreWithoutFree()
};
}
}
}
}
11 changes: 6 additions & 5 deletions Lagrange.Core.NativeAPI/NativeModel/Common/BotSignProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,8 @@ internal class AndroidSignProvider(string? signUrl) : AndroidBotSignProvider, ID
["seq"] = seq,
["buffer"] = Convert.ToHexString(body.Span),
["guid"] = Convert.ToHexString(Context.Keystore.Guid),
["version"] = Context.AppInfo.PtVersion
["version"] = Context.AppInfo.PtVersion,
["qua"] = Context.AppInfo.Qua
};

var response = await _client.PostAsync($"{_url}/sign", new StringContent(payload.ToJsonString(), Encoding.UTF8, "application/json"));
Expand Down Expand Up @@ -305,7 +306,8 @@ public override async Task<byte[]> GetEnergy(long uin, string data)
["data"] = data,
["guid"] = Convert.ToHexString(Context.Keystore.Guid),
["ver"] = Context.AppInfo.SdkInfo.SdkVersion,
["version"] = Context.AppInfo.PtVersion
["version"] = Context.AppInfo.PtVersion,
["qua"] = Context.AppInfo.Qua
};

var response = await _client.PostAsync($"{_url}/energy", new StringContent(payload.ToJsonString(), Encoding.UTF8, "application/json"));
Expand All @@ -330,7 +332,8 @@ public override async Task<byte[]> GetDebugXwid(long uin, string data)
["uin"] = uin,
["data"] = data,
["guid"] = Convert.ToHexString(Context.Keystore.Guid),
["version"] = Context.AppInfo.PtVersion
["version"] = Context.AppInfo.PtVersion,
["qua"] = Context.AppInfo.Qua
};

var response = await _client.PostAsync($"{_url}/get_tlv553", new StringContent(payload.ToJsonString(), Encoding.UTF8, "application/json"));
Expand Down Expand Up @@ -371,12 +374,10 @@ internal class SignResponse
internal static partial class JsonHelper
{
[JsonSourceGenerationOptions(GenerationMode = JsonSourceGenerationMode.Default, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)]

[JsonSerializable(typeof(AndroidSignProvider.ResponseRoot<AndroidSignProvider.SignResponse>))]
[JsonSerializable(typeof(AndroidSignProvider.ResponseRoot<string>))]
[JsonSerializable(typeof(LinuxSignProvider.Root))]
[JsonSerializable(typeof(LinuxSignProvider.Response))]

[JsonSerializable(typeof(JsonObject))]
[JsonSerializable(typeof(LightApp))]
private partial class CoreSerializerContext : JsonSerializerContext;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ public struct ByteArrayDictNative
{
public int Length;
public IntPtr Data;

public static implicit operator ByteArrayDictNative(ByteArrayKVPNative[] dict)
{
int size = Marshal.SizeOf<ByteArrayKVPNative>();
Expand All @@ -15,26 +15,26 @@ public static implicit operator ByteArrayDictNative(ByteArrayKVPNative[] dict)
{
Marshal.StructureToPtr(dict[i], ptr + i * size, false);
}

return new ByteArrayDictNative { Length = dict.Length, Data = ptr };
}

public static implicit operator ByteArrayKVPNative[](ByteArrayDictNative dict)
{
if (dict.Data == IntPtr.Zero || dict.Length == 0)
{
return [];
}

ByteArrayKVPNative[] result = new ByteArrayKVPNative[dict.Length];
int size = Marshal.SizeOf<ByteArrayKVPNative>();
for (int i = 0; i < dict.Length; i++)
{
result[i] = Marshal.PtrToStructure<ByteArrayKVPNative>(dict.Data + i * size);
}
Marshal.FreeHGlobal(dict.Data);

// Marshal.FreeHGlobal(dict.Data); Why release here?

return result;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public ReverseEventCountStruct() { }
public int BotLogEventCount = 0;
public int BotMessageEventCount = 0;
public int BotNewDeviceVerifyEventCount = 0;
public int BotOfflineEventCount = 0;
public int BotOnlineEventCount = 0;
public int BotQrCodeEventCount = 0;
public int BotQrCodeQueryEventCount = 0;
Expand Down
21 changes: 18 additions & 3 deletions Lagrange.Core.NativeAPI/Program.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Runtime.InteropServices;
using System.Text;
using Lagrange.Core.Common;
using Lagrange.Core.Common.Interface;
using Lagrange.Core.NativeAPI.NativeModel.Common;
Expand Down Expand Up @@ -37,8 +38,9 @@ public static int Initialize(IntPtr botConfigPtr, IntPtr keystorePtr, IntPtr app
return index;
}

//uin, password皆可选,传入 0 或结构体内Data/Length置0
[UnmanagedCallersOnly(EntryPoint = "Start")]
public static StatusCode Start(int index)
public static StatusCode Start(int index, long uin, ByteArrayNative password)
{
if (Contexts.Count <= index)
{
Expand All @@ -50,9 +52,22 @@ public static StatusCode Start(int index)
return StatusCode.AlreadyStarted;
}

if (uin == 0 || password.IsEmpty())
{
Task.Run(async () =>
{
await Contexts[index].BotContext.Login();
await Task.Delay(Timeout.Infinite);
});

return StatusCode.Success;
}

var passwordData = Encoding.UTF8.GetString(password.ToByteArrayWithoutFree());

Task.Run(async () =>
{
await Contexts[index].BotContext.Login();
await Contexts[index].BotContext.Login(uin, passwordData);
await Task.Delay(Timeout.Infinite);
});

Expand Down Expand Up @@ -80,4 +95,4 @@ public static void FreeMemory(IntPtr ptr)
Marshal.FreeHGlobal(ptr);
}
}
}
}
7 changes: 4 additions & 3 deletions Lagrange.Core.NativeAPI/ReverseEvent/EventEntryPoint.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ public static IntPtr GetEventCount(int index)
BotLogEventCount = Program.Contexts[index].EventInvoker.BotLogEvent.Events.Count,
BotMessageEventCount = Program.Contexts[index].EventInvoker.BotMessageEvent.Events.Count,
BotNewDeviceVerifyEventCount = Program.Contexts[index].EventInvoker.BotNewDeviceVerifyEvent.Events.Count,
BotOfflineEventCount = Program.Contexts[index].EventInvoker.BotOfflineEvent.Events.Count,
BotOnlineEventCount = Program.Contexts[index].EventInvoker.BotOnlineEvent.Events.Count,
BotQrCodeEventCount = Program.Contexts[index].EventInvoker.BotQrCodeEvent.Events.Count,
BotQrCodeQueryEventCount = Program.Contexts[index].EventInvoker.BotQrCodeQueryEvent.Events.Count,
Expand Down Expand Up @@ -172,7 +173,7 @@ public static IntPtr GetBotGroupReactionEvent(int index)

return eventPtr;
}

[UnmanagedCallersOnly(EntryPoint = "GetBotGroupRecallEvent")]
public static IntPtr GetBotGroupRecallEvent(int index)
{
Expand All @@ -183,7 +184,7 @@ public static IntPtr GetBotGroupRecallEvent(int index)

var botGroupRecallEvent = Program.Contexts[index].EventInvoker.BotGroupRecallEvent;

IntPtr eventPtr = GetEventStructPtr<BotGroupReactionEventStruct>(botGroupRecallEvent);
IntPtr eventPtr = GetEventStructPtr<BotGroupRecallEventStruct>(botGroupRecallEvent);

return eventPtr;
}
Expand Down Expand Up @@ -369,4 +370,4 @@ private static IntPtr GetEventStructPtr<T>(ReverseEventBase reverseEvent) where
return resultPtr;
}
}
}
}
7 changes: 4 additions & 3 deletions Lagrange.Core.NativeAPI/ReverseEvent/ReverseEventInvoker.cs
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
using Lagrange.Core.NativeAPI.ReverseEvent.Abstract;

namespace Lagrange.Core.NativeAPI.ReverseEvent
namespace Lagrange.Core.NativeAPI.ReverseEvent
{
public class ReverseEventInvoker
{
public ReverseEventInvoker(BotContext context)
{
BotCaptchaEvent.RegisterEventHandler(context);
BotFriendRequestEvent.RegisterEventHandler(context);
BotFriendRecallEvent.RegisterEventHandler(context);
BotGroupInviteNotificationEvent.RegisterEventHandler(context);
BotGroupJoinNotificationEvent.RegisterEventHandler(context);
BotGroupMemberDecreaseEvent.RegisterEventHandler(context);
BotGroupMemberIncreaseEvent.RegisterEventHandler(context);
BotGroupNudgeEvent.RegisterEventHandler(context);
BotGroupReactionEvent.RegisterEventHandler(context);
BotGroupRecallEvent.RegisterEventHandler(context);
BotLoginEvent.RegisterEventHandler(context);
BotLogEvent.RegisterEventHandler(context);
BotMessageEvent.RegisterEventHandler(context);
Expand All @@ -23,6 +23,7 @@ public ReverseEventInvoker(BotContext context)
BotQrCodeEvent.RegisterEventHandler(context);
BotQrCodeQueryEvent.RegisterEventHandler(context);
BotRefreshKeystoreEvent.RegisterEventHandler(context);
BotSMSEvent.RegisterEventHandler(context);
}

public BotCaptchaReverseEvent BotCaptchaEvent { get; } = new();
Expand Down
23 changes: 23 additions & 0 deletions Lagrange.Core/Internal/Logic/WtExchangeLogic.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using System;
using System.Collections.Concurrent;
using System.Numerics;
using System.Text;
using System.Web;
using Lagrange.Core.Common;
Expand Down Expand Up @@ -206,6 +208,27 @@ private async Task<bool> ManualLogin(long uin, string? password)

_token?.ThrowIfCancellationRequested();
result = await _context.EventContext.SendEvent<LoginEventResp>(new LoginEventReq(LoginEventReq.Command.Captcha) { Ticket = ticket });

// --- Patch begin ---
if (result.State == LoginEventResp.States.SmsRequired)
{
string? url = null;
if (result.Tlvs.TryGetValue(0x204, out var tlv204)) {
url = Encoding.UTF8.GetString(tlv204);
}

var tlv178 = new BinaryPacket(result.Tlvs[0x178].AsSpan());
string countryCode = tlv178.ReadString(Prefix.Int16 | Prefix.LengthOnly);
string phone = tlv178.ReadString(Prefix.Int16 | Prefix.LengthOnly);

_context.LogInfo(Tag, "SMS Verification required, Phone: {0}-{1} | URL: {2}", countryCode, phone, url);
_context.EventInvoker.PostEvent(new BotSMSEvent(url, $"{countryCode}-{phone}"));

_smsSource = new TaskCompletionSource<string>();
string code = await _smsSource.Task;
result = await _context.EventContext.SendEvent<LoginEventResp>(new LoginEventReq(LoginEventReq.Command.SubmitSMSCode) { Code = code });
}
// --- Patch end ---
}

if (result.State == LoginEventResp.States.DeviceLockViaSmsNewArea)
Expand Down
12 changes: 6 additions & 6 deletions Lagrange.Core/Internal/Services/Login/LoginService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ internal class LoginService : BaseService<LoginEventReq, LoginEventResp>
protected override ValueTask<ReadOnlyMemory<byte>> Build(LoginEventReq input, BotContext context)
{
if (!_packet.IsValueCreated) _packet = new Lazy<WtLogin>(() => new WtLogin(context));

return input.Cmd switch
{
LoginEventReq.Command.Tgtgt => new ValueTask<ReadOnlyMemory<byte>>(_packet.Value.BuildOicq09()),
LoginEventReq.Command.Tgtgt => new ValueTask<ReadOnlyMemory<byte>>(_packet.Value.BuildOicq09()),
_ => throw new ArgumentOutOfRangeException(nameof(input), $"Unknown command: {input.Cmd}")
};
}
Expand All @@ -48,7 +48,7 @@ protected override async ValueTask<ReadOnlyMemory<byte>> Build(LoginEventReq inp

return input.Cmd switch
{
LoginEventReq.Command.Tgtgt => await _packet.Value.BuildOicq09Android(input.Password),
LoginEventReq.Command.Tgtgt => await _packet.Value.BuildOicq09Android(input.Password),
LoginEventReq.Command.Captcha => await _packet.Value.BuildOicq02Android(input.Ticket),
LoginEventReq.Command.FetchSMSCode => await _packet.Value.BuildOicq08Android(),
LoginEventReq.Command.SubmitSMSCode => await _packet.Value.BuildOicq07Android(input.Code),
Expand All @@ -72,7 +72,7 @@ public static LoginEventResp Parse(WtLogin packet, ReadOnlyMemory<byte> input, B
var payload = packet.Parse(input.Span, out ushort command);
var reader = new BinaryPacket(payload);
Debug.Assert(command == 0x810);

ushort internalCmd = reader.Read<ushort>();
byte state = reader.Read<byte>();
var tlvs = ProtocolHelper.TlvUnPack(ref reader);
Expand All @@ -83,7 +83,7 @@ public static LoginEventResp Parse(WtLogin packet, ReadOnlyMemory<byte> input, B
uint _ = errorReader.Read<uint>(); // error code
string errorTitle = errorReader.ReadString(Prefix.Int16 | Prefix.LengthOnly);
string errorMessage = errorReader.ReadString(Prefix.Int16 | Prefix.LengthOnly);

return new LoginEventResp(state, (errorTitle, errorMessage));
}

Expand All @@ -93,7 +93,7 @@ public static LoginEventResp Parse(WtLogin packet, ReadOnlyMemory<byte> input, B
var tlv119 = TeaProvider.CreateDecryptSpan(tgtgt);
var tlv119Reader = new BinaryPacket(tlv119);
var tlvCollection = ProtocolHelper.TlvUnPack(ref tlv119Reader);

return new LoginEventResp(state, tlvCollection);
}

Expand Down
Loading
Loading