mirror of
https://gitlab.com/Syroot/Worms.git
synced 2025-01-27 22:27:58 +03:00
Finalize OW password encryption and decryption.
This commit is contained in:
parent
1c401235d5
commit
61377411a1
@ -11,7 +11,7 @@ namespace Syroot.Worms.OnlineWorms.Launcher
|
||||
|
||||
public string UserName { get; set; }
|
||||
public string Password { get; set; }
|
||||
public int PasswordKey { get; set; }
|
||||
public uint PasswordKey { get; set; }
|
||||
|
||||
public string ExecutablePath { get; set; } = "DWait.exe";
|
||||
public string ExecutableArgs { get; set; }
|
||||
|
@ -1,16 +1,16 @@
|
||||
{
|
||||
// Server connection
|
||||
"ServerIP": "127.0.0.1",
|
||||
"ServerPort": "17022",
|
||||
"ServerPort": 17022,
|
||||
|
||||
// Autologin credentials (optional)
|
||||
"UserName": "UserName",
|
||||
"Password": "Password",
|
||||
|
||||
// Debugging settings (optional)
|
||||
"PasswordKey": "0", // base value to encrypt and decrypt password in launch file mapping
|
||||
"PasswordKey": 1000, // base value to encrypt and decrypt password in launch file mapping
|
||||
"ExecutablePath": "DWait.exe", // relative or absolute path to game executable
|
||||
"ExecutableArgs": "", // additional arguments appended to command line
|
||||
"MappingName": "KG1234567890", // launch file mapping identifier used and passed as first argument to game
|
||||
"StartSuspended": "false" // true to create, but wait for confirmation to run the game process (to attach debuggers)
|
||||
"StartSuspended": false // true to create, but wait for confirmation to run the game process (to attach debuggers)
|
||||
}
|
@ -11,7 +11,6 @@ namespace Syroot.Worms.Scratchpad
|
||||
|
||||
private static void Main(string[] args)
|
||||
{
|
||||
TestLaunchConfigEncryption();
|
||||
}
|
||||
|
||||
private static void ConvertKsfImages()
|
||||
@ -45,12 +44,6 @@ namespace Syroot.Worms.Scratchpad
|
||||
}
|
||||
}
|
||||
|
||||
private static void TestLaunchConfigEncryption()
|
||||
{
|
||||
LaunchConfig launchConfig = new LaunchConfig();
|
||||
launchConfig.DecryptPassword("Unknown", 0);
|
||||
}
|
||||
|
||||
private static void WriteMemoryManagerBlocks()
|
||||
{
|
||||
// Memory manager block allocation simulation.
|
||||
|
@ -12,10 +12,25 @@ namespace Syroot.Worms.OnlineWorms
|
||||
/// </summary>
|
||||
public class LaunchConfig
|
||||
{
|
||||
// ---- CONSTANTS ----------------------------------------------------------------------------------------------
|
||||
|
||||
private const int _bufferSize = 64 * sizeof(uint);
|
||||
private const string _passwordCharacters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
|
||||
// ---- FIELDS -------------------------------------------------------------------------------------------------
|
||||
|
||||
private static readonly Encoding _win949Encoding;
|
||||
private static readonly char[] _invalidUserNameChars = { '=', '&', ' ' };
|
||||
private static readonly byte[] _passwordDecryptShifts = new byte[]
|
||||
{
|
||||
0x12, 0x1D, 0x07, 0x19, 0x0F, 0x1F, 0x16, 0x1B, 0x09, 0x1A, 0x03, 0x0D, 0x13, 0x0E, 0x14, 0x0B,
|
||||
0x05, 0x02, 0x17, 0x10, 0x0A, 0x18, 0x1C, 0x11, 0x06, 0x1E, 0x00, 0x15, 0x0C, 0x08, 0x04, 0x01
|
||||
};
|
||||
private static readonly byte[] _passwordEncryptShifts = new byte[]
|
||||
{
|
||||
0x1A, 0x1F, 0x11, 0x0A, 0x1E, 0x10, 0x18, 0x02, 0x1D, 0x08, 0x14, 0x0F, 0x1C, 0x0B, 0x0D, 0x04,
|
||||
0x13, 0x17, 0x00, 0x0C, 0x0E, 0x1B, 0x06, 0x12, 0x15, 0x03, 0x09, 0x07, 0x16, 0x01, 0x19, 0x05
|
||||
};
|
||||
|
||||
private string _userName;
|
||||
private string _passwordString;
|
||||
@ -100,8 +115,10 @@ namespace Syroot.Worms.OnlineWorms
|
||||
/// </summary>
|
||||
public string GetPassword()
|
||||
{
|
||||
// TODO: Decrypt password:
|
||||
return _passwordString;
|
||||
if (_passwordString == null)
|
||||
return null;
|
||||
string[] parts = _passwordString.Split(';');
|
||||
return DecryptPassword(parts[1], UInt32.Parse(parts[2]));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -110,71 +127,82 @@ namespace Syroot.Worms.OnlineWorms
|
||||
/// </summary>
|
||||
/// <param name="password">The password to store encrypted.</param>
|
||||
/// <param name="key">The key to encrypt with.</param>
|
||||
public void SetPassword(string password, int key)
|
||||
public void SetPassword(string password, uint key = 1000)
|
||||
{
|
||||
// TODO: Encrypt password.
|
||||
_passwordString = $";{password};{key}";
|
||||
_passwordString = $";{EncryptPassword(password, key)};{key}";
|
||||
}
|
||||
|
||||
// ---- METHODS (PRIVATE) --------------------------------------------------------------------------------------
|
||||
|
||||
public string DecryptPassword(string data, int key)
|
||||
private string EncryptPassword(string password, uint key)
|
||||
{
|
||||
byte[] decodeBuffer = new byte[64];
|
||||
int decodeIdx = 0;
|
||||
int idx = 0;
|
||||
do
|
||||
using (MemoryStream inStream = new MemoryStream(new byte[_bufferSize]))
|
||||
{
|
||||
int subIdx = 0;
|
||||
uint curValue = 0;
|
||||
string dataRemain = data.Substring(idx);
|
||||
do
|
||||
// Write input into a buffer. Required to loop over the input password end.
|
||||
inStream.WriteString(password, StringCoding.ZeroTerminated, Encoding.ASCII);
|
||||
inStream.Position = 0;
|
||||
using (MemoryStream outStream = new MemoryStream(new byte[_bufferSize]))
|
||||
{
|
||||
uint baseValue = 1;
|
||||
if (subIdx > 0)
|
||||
// Encrypt the contents character by character.
|
||||
while (inStream.Position < password.Length)
|
||||
{
|
||||
int subIdxCounter = subIdx;
|
||||
do
|
||||
// Begin a new dword value at every 7th index.
|
||||
uint dword = CryptDword(inStream.ReadUInt32() + key, true);
|
||||
for (int j = 0; j < 7; j++)
|
||||
{
|
||||
baseValue *= 36;
|
||||
subIdxCounter--;
|
||||
} while (subIdxCounter != 0);
|
||||
outStream.WriteByte((byte)_passwordCharacters[(int)(dword % _passwordCharacters.Length)]);
|
||||
dword /= (uint)_passwordCharacters.Length;
|
||||
}
|
||||
}
|
||||
char c = dataRemain[subIdx];
|
||||
uint factor = (uint)(c < '0' || c > '9' ? c - '7' : c - '0');
|
||||
curValue += baseValue * factor;
|
||||
++subIdx;
|
||||
} while (subIdx < 7);
|
||||
idx += 7;
|
||||
int value = DecryptValue(curValue, 0) - key;
|
||||
Buffer.BlockCopy(BitConverter.GetBytes(value), 0, decodeBuffer, decodeIdx++, sizeof(int));
|
||||
} while (idx < data.Length);
|
||||
return Encoding.ASCII.GetString(decodeBuffer);
|
||||
// Return the encrypted password as a zero-terminated ASCII string.
|
||||
outStream.Position = 0;
|
||||
return outStream.ReadString(StringCoding.ZeroTerminated, Encoding.ASCII);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int DecryptValue(uint value, int shiftArrayIndex)
|
||||
private string DecryptPassword(string encryptedPassword, uint key)
|
||||
{
|
||||
int[][] shifts = new int[][]
|
||||
using (MemoryStream inStream = new MemoryStream(new byte[_bufferSize]))
|
||||
{
|
||||
new[] { 18, 29, 7, 25, 15, 31, 22, 27, 9, 26, 3, 13, 19, 14, 20, 11, 5, 2, 23, 16, 10, 24, 28, 17, 6, 30, 0, 21, 12, 8, 4, 1 },
|
||||
new[] { 26, 31, 17, 10, 30, 16, 24, 2, 29, 8, 20, 15, 28, 11, 13, 4, 19, 23, 0, 12, 14, 27, 6, 18, 21, 3, 9, 22, 7, 1, 25, 5 }
|
||||
};
|
||||
|
||||
int result = 0;
|
||||
if (value != 0)
|
||||
{
|
||||
int idx = 0;
|
||||
do
|
||||
// Write input into a buffer. Required to loop over the input password end.
|
||||
inStream.WriteString(encryptedPassword, StringCoding.Raw, Encoding.ASCII);
|
||||
inStream.Position = 0;
|
||||
using (MemoryStream outStream = new MemoryStream(new byte[_bufferSize]))
|
||||
{
|
||||
uint highBits = (uint)(value - (value & ~1));
|
||||
value >>= 1; // / 2
|
||||
if (highBits != 0)
|
||||
// Decrypt the contents character by character.
|
||||
for (int i = 0; i < encryptedPassword.Length; i += 7)
|
||||
{
|
||||
int shift = shifts[shiftArrayIndex][idx];
|
||||
result += (int)(highBits << shift);
|
||||
uint dword = 0;
|
||||
for (int j = 0; j < 7; j++)
|
||||
{
|
||||
byte b = inStream.Read1Byte();
|
||||
uint op1 = (uint)Math.Pow(_passwordCharacters.Length, j);
|
||||
uint op2 = (uint)(b < '0' || b > '9' ? b - '7' : b - '0');
|
||||
dword += op1 * op2;
|
||||
}
|
||||
// Finalize a new dword value at every 7th index.
|
||||
outStream.WriteUInt32(CryptDword(dword, false) - key);
|
||||
}
|
||||
idx++;
|
||||
} while (value != 0);
|
||||
// Return the decrypted password as a zero-terminated ASCII string.
|
||||
outStream.Position = 0;
|
||||
return outStream.ReadString(StringCoding.ZeroTerminated, Encoding.ASCII);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private uint CryptDword(uint dword, bool encrypt)
|
||||
{
|
||||
// Shift least to most significant bits into the resulting value by an amount stored in a one-way array.
|
||||
byte[] shifts = encrypt ? _passwordEncryptShifts : _passwordDecryptShifts;
|
||||
|
||||
uint result = 0;
|
||||
int shiftIndex = 0;
|
||||
while (dword > 0)
|
||||
{
|
||||
result += (dword & 1) << shifts[shiftIndex];
|
||||
shiftIndex++;
|
||||
dword >>= 1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -6,6 +6,7 @@
|
||||
<Copyright>(c) Syroot, licensed under MIT</Copyright>
|
||||
<Description>.NET library for loading and modifying files of Team17 Worms games.</Description>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<PackageIconUrl>https://gitlab.com/Syroot/Worms/raw/master/res/icon.png</PackageIconUrl>
|
||||
<PackageId>Syroot.Worms</PackageId>
|
||||
<PackageLicenseUrl>https://gitlab.com/Syroot/Worms/raw/master/LICENSE</PackageLicenseUrl>
|
||||
|
Loading…
x
Reference in New Issue
Block a user