SilkroadSecurityApi improvement and more features by 'Dentrax'
Ultra simple Silkroad Proxy Library Ever!
Don't repeat yourself every time!
Click here for Guide & Theory
EasySSA
EasySSA library for VSRO files is an easy and advanced way to create proxy programs.
Uses : .NET Framework v4.6.1 Library
Controls and wizards are available for users to:
- Detect, block, replace, ignore features to incoming-outgoing packets
- Analyze server-side or client-side packets with details more details
- Replace, Inject, Response and Ingore incoming-outgoing packets and accept/deny or disconnect client with one line code only. See here for example.
- Advanced packet database library. Click here to see PacketDatabase.cs
- Packet.cs is obsolete! The new SROPacket.cs is overriding now.
- Not complex, not hard, dont repeat yourself.
SROServiceComponent gateway = new SROServiceComponent(ServerServiceType, Index);
Function | Parameter | Explanation |
---|---|---|
SetFingerprint |
Fingerprint | Sets a fingerprint for Security. Uses IdentityID, IdentityFlag, SecurityFlag. |
SetLocalEndPoint |
IPEndPoint | Associates a Socket with local endpoint. |
SetServiceEndPoint |
IPEndPoint | Associates a Socket with service/module endpoint. |
SetMaxClientCount |
int | How many clients can connect the prxoy ? |
SetLocalBindTimeout |
int | Sets local bind timeout. |
SetServiceBindTimeout |
int | Sets service bind timeout. |
SetDebugMode |
bool | Sets debug mode. |
DOBind |
Action<bool, BindErrorType> | Initialize component and start listening the server. |
Listener | Type | Explanation |
---|---|---|
OnLocalSocketStatusChanged |
Action | Trigger if local socket status changed some reason. (readonly) |
OnServiceSocketStatusChanged |
Action<Client, SocketError> | Trigger if service socket status changed some reason. (readonly) |
OnClientConnected |
Func<Client, bool> | Trigger if a client socket established. To accept or decline a client use return true or return false |
OnClientDisconnected |
Action<Client, ClientDisconnectType> | Trigger if a client socket disconnected due to a error or problem. (readonly) |
OnPacketReceived |
Func<Client, SROPacket, PacketSocketType, PacketResult> | Trigger if a packet received from a client. |
PacketOperationType | PacketResult Type | PacketResult Parameter | Explanation |
---|---|---|---|
RESPONSE |
PacketResult.PacketResponseResultInfo | List packet or Packet packet | Send packet response list to ServiceContext where the packet comes from. |
DISCONNECT |
PacketResult.PacketDisconnectResultInfo | string notice, Enum disconnectReason | Send notice to client before disconnect if possible. |
REPLACE |
PacketResult.PacketReplaceResultInfo | Packet packet, List replaceWith | Replace current packet with replaceWith array if current packet == packet. |
INJECT |
PacketResult.PacketInjectResultInfo | Packet packet, List injectWith, bool afterPacket | Inject injectWith packets if current packet == packet. Inject after if afterPacket true. |
IGNORE |
Independent | Parameterless | Ignore current packet. Dont send. |
NOTHING |
Independent | Parameterless | Nothing |
BindErrorType | Explanation |
---|---|
SUCCESS |
Trigger if everything is great and TCP listener socket bind successfull. |
COMPONENT_DISPOSED |
Trigger if SROServiceComponent object disposed. |
COMPONENT_FINGERPRINT_NULL |
Trigger if Fingerprint object is null. |
COMPONENT_LOCAL_ENDPOINT_NULL |
Trigger if local socket's endpoint is null. |
COMPONENT_SERVICE_ENDPOINT_NULL |
Trigger if service socket's endpoint is null. |
COMPONENT_LOCAL_BIND_TIMEOUT_NULL_OR_ZERO |
Trigger if local socket's timeout null or under 1. |
COMPONENT_SERVICE_BIND_TIMEOUT_NULL_OR_ZERO |
Trigger if service socket's timeout null or under 1. |
COMPONENT_SERVICE_INDEX_NULL_OR_ZERO |
Trigger if service index null or under 1. |
COMPONENT_SERVICE_CLIENT_COUNT_NULL_OR_ZERO |
Trigger if max client count null or under 1. |
SERVER_BIND_SOCKET_NOT_NULL |
Trigger if TCP listener socket is not null. |
SERVER_BIND_SOCKET_ALREADY_ACTIVE |
Trigger if TCP listener socket is already listening and not null. |
SERVER_BIND_SOCKET_NON_AVAILABLE |
Trigger if TCP listener socket bind failed or available == 0. |
SERVER_BIND_ARGUMENT_NULL_EXCEPTION |
Trigger if TCP listener catch ArgumentNullException |
SERVER_BIND_SOCKET_EXCEPTION |
Trigger if TCP listener catch SocketException |
SERVER_BIND_SECURITY_EXCEPTION |
Trigger if TCP listener catch SecurityException |
SERVER_BIND_OBJECT_DISPOSED_EXCEPTION |
Trigger if TCP listener catch ObjectDisposedException |
UNKNOWN |
Trigger if a unexcepted error handled. |
AccountStatusType | Explanation |
---|---|
ALREADY_LOGGED_ON |
Trigger if account already logged on status. |
LOGIN_SUCCESS |
Trigger if account login success. |
LOGIN_FAILED |
Trigger if account login failed. Wrong (ID, PW). |
BLOCKED |
Trigger if account login blocked when over captcha or login try. |
BANNED |
Trigger if account login banned from GM. |
ClientStatusType | Explanation |
---|---|
STARTED |
Trigger if sro_client started successfully. |
SHUTDOWN |
Trigger if sro_client closed or crashed some reason. |
SWITCH_TO_CLIENT_SUCCESS |
Trigger if clientless to client switch successfully. |
SWITCH_TO_CLIENT_FAILED |
Trigger if clientless to client switch failed. |
SWITCH_TO_CLIENTLESS_SUCCESS |
Trigger if client to clientless switch successfully. |
SWITCH_TO_CLIENTLESS_FAILED |
Trigger if client to clientless switch failed. |
READY |
Trigger if sro_client fully ready up when the character enters the game. |
ClientStatusType | Explanation |
---|---|
FETCH |
Trigger if captcha code fetched successfully. |
CORRECT |
Trigger if captcha code entered correct. |
WRONG |
Trigger if captcha code entered wrong. |
CharacterStatusType | Explanation |
---|---|
NAME_NOT_FOUND |
Trigger if no character found with name. |
SELECT_SUCCESS |
Trigger if character selected successfully. |
SELECT_FAILED |
Trigger if character select failed. |
LOGIN_SUCCESS |
Trigger if character login success to GameWorld. |
LOGIN_FAILED |
Trigger if character login failed to GameWorld. |
SPAWN_SUCCESS |
Trigger if character spawned and ready up to GameWorld. |
SPAWN_FAILED |
Trigger if character spawn failed. |
NO_CHARACTERS_FOUND |
Trigger if there is no character available. (Count == 0) |
SROServiceComponent gateway = new SROServiceComponent(ServerServiceType.GATEWAY, 1)
.SetFingerprint(new Fingerprint("SR_Client", 0, SecurityFlags.Handshake & SecurityFlags.Blowfish & SecurityFlags.SecurityBytes, ""))
.SetLocalEndPoint(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 15779))
.SetLocalBindTimeout(10)
.SetServiceEndPoint(new IPEndPoint(IPAddress.Parse("111.111.111.111"), 15779))
.SetServiceBindTimeout(100)
.SetMaxClientCount(500)
.SetDebugMode(false);
gateway.OnLocalSocketStatusChanged += new Action<SocketError>(delegate (SocketError error) {
if (error == SocketError.Success) {
Console.WriteLine("LOCAL socket bind SUCCESS! : " + gateway.LocalEndPoint.ToString());
} else {
Console.WriteLine("LOCAL socket bind FAILED! : " + error);
}
});
gateway.OnServiceSocketStatusChanged += new Action<Client, SocketError>(delegate (Client client, SocketError error) {
if (error == SocketError.Success) {
Console.WriteLine("SERVICE socket connect SUCCESS! : " + gateway.ServiceEndPoint.ToString());
} else {
Console.WriteLine("SERVICE socket connect FAILED! : " + error);
}
});
gateway.OnClientConnected += new Func<Client, bool>(delegate (Client client) {
Console.WriteLine("New client connected : " + client.Socket.RemoteEndPoint);
if (string.IsNullOrEmpty(client.IPAddress)) { //Example
return false; //Decline client
} else {
return true; //Accept client
}
});
gateway.OnClientDisconnected += new Action<Client, ClientDisconnectType>(delegate (Client client, ClientDisconnectType disconnectType) {
Console.WriteLine("Client disconnected : " + client.IPAddress + " -- Reason : " + disconnectType);
});
gateway.OnPacketReceived += new Func<Client, SROPacket, PacketSocketType, PacketResult>(delegate (Client client, SROPacket packet, PacketSocketType socketType) {
switch (packet.Opcode) {
case 0x1111:
return new PacketResult(PacketOperationType.DISCONNECT, new PacketResult.PacketDisconnectResultInfo("DC Reason : 0x5555 received"));
case 0x2222:
return new PacketResult(PacketOperationType.IGNORE);
case 0x3333:
return new PacketResult(PacketOperationType.INJECT, new PacketResult.PacketInjectResultInfo(packet, new List<Packet> { new Packet(0x3334), new Packet(0x3335) }, true));
case 0x4444:
return new PacketResult(PacketOperationType.REPLACE, new PacketResult.PacketReplaceResultInfo(packet, new List<Packet> { new Packet(0x4445) }));
case 0x5555:
return new PacketResult(PacketOperationType.RESPONSE, new PacketResult.PacketResponseResultInfo(new Packet(0x5556)));
default:
return new PacketResult(PacketOperationType.NOTHING);
}
});
gateway.DOBind(delegate (bool success, BindErrorType error) {
if (success) {
Console.WriteLine("EasySSA bind SUCCESS");
} else {
Console.WriteLine("EasySSA bind FAILED -- Reason : " + error);
}
});
SROClientComponent clientComponent = new SROClientComponent(1)
.SetFingerprint(new Fingerprint("SR_Client", 0, SecurityFlags.Handshake & SecurityFlags.Blowfish & SecurityFlags.SecurityBytes, string.Empty))
.SetAccount(new Account("furkan", "1"), "Dentrax")
.SetCaptcha(string.Empty)
.SetVersionID(191)
.SetLocaleID(22)
.SetClientless(false)
.SetClientPath("D:\\vSRO\\vSRO Client")
.SetLocalAgentEndPoint(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 25880))
.SetLocalGatewayEndPoint(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 25779))
.SetServiceEndPoint(new IPEndPoint(IPAddress.Parse("111.111.111.111"), 15779))
.SetBindTimeout(100)
.SetDebugMode(false);
clientComponent.OnClientStatusChanged += new Action<SROClient, ClientStatusType>(delegate (SROClient client, ClientStatusType status) {
});
clientComponent.OnAccountStatusChanged += new Action<SROClient, AccountStatusType>(delegate (SROClient client, AccountStatusType status) {
});
clientComponent.OnCaptchaStatusChanged += new Action<SROClient, CaptchaStatusType>(delegate (SROClient client, CaptchaStatusType status) {
});
clientComponent.OnCharacterStatusChanged += new Action<SROClient, CharacterStatusType>(delegate (SROClient client, CharacterStatusType status) {
});
clientComponent.OnLocalSocketStatusChanged += new Action<SocketError>(delegate (SocketError error) {
if (error == SocketError.Success) {
Console.WriteLine("LOCAL socket bind SUCCESS! : " + clientComponent.LocalGatewayEndPoint.ToString());
} else {
Console.WriteLine("LOCAL socket bind FAILED! : " + error);
}
});
clientComponent.OnServiceSocketStatusChanged += new Action<SROClient, SocketError>(delegate (SROClient client, SocketError error) {
if (error == SocketError.Success) {
Console.WriteLine("SERVICE socket connect SUCCESS! : " + clientComponent.ServiceEndPoint.ToString());
} else {
Console.WriteLine("SERVICE socket connect FAILED! : " + error);
}
});
clientComponent.OnSocketConnected += new Action<SROClient, bool>(delegate (SROClient client, bool connected) {
Console.WriteLine("New client connected : " + client.Socket.RemoteEndPoint);
});
clientComponent.OnSocketDisconnected += new Action<SROClient, ClientDisconnectType>(delegate (SROClient client, ClientDisconnectType disconnectType) {
Console.WriteLine("Client disconnected : " + client.IPAddress + " -- Reason : " + disconnectType);
});
clientComponent.OnPacketReceived += new Func<SROClient, SROPacket, PacketSocketType, PacketResult>(delegate (SROClient client, SROPacket packet, PacketSocketType socketType) {
return new PacketResult(PacketOperationType.NOTHING);
});
clientComponent.DOBind(delegate (bool success, BindErrorType error) {
if (success) {
Console.WriteLine("EasySSA bind SUCCESS");
} else {
Console.WriteLine("EasySSA bind FAILED -- Reason : " + error);
}
});
EasySSA was created to serve three purposes:
EasySSA is a server-client proxy tool which logs all SilkroadOnline packet traffic between your server and the client with SilkroadSecurityApi
-
To act as a library to create simplest security for VSRO server files.
-
To provide a simplest way to create any feature, what you think.
-
Instead of writing long and complex code every time, it provides the easiest and strongest way.
Project Manager - Furkan Türkal (GitHub: dentrax)
We publish source for the [EasySSA] in three rolling branches:
We publish source for the engine in three rolling branches:
The release branch is extensively tested by our QA team and makes a great starting point for learning the EasySSA.
The promoted branch is updated with builds for our team members to use. It's a good balance between getting the latest cool stuff and knowing most things work.
The master branch tracks live changes by our EasySSA team. This is the cutting edge and may be buggy - it may not even compile.
Other short-lived branches may pop-up from time to time as we stabilize new releases or hotfixes.
The base project code is copyrighted by Furkan 'Dentrax' Türkal and is covered by single licence.
All program code (i.e. C#, Java) is licensed under MIT unless otherwise specified. Please see the LICENSE.md file for more information.
SilkroadSecurityApi
It was developed and made by Drew 'pushedx' Benton. For more information, please click here
Please check the CONTRIBUTING.md file for contribution instructions and naming guidelines.
EasySSA was created by Furkan 'Dentrax' Türkal
You can contact EasySSA by URL: CONTACT
Best Regards