Files
2026-05-06 07:47:36 +02:00

288 lines
12 KiB
C#

// !! this file should not be modified
using System;
using System.Runtime.InteropServices; // so we can marshal the DRIS as a block of memory
using System.Text; // so we can extract / set strings in the DRIS
using System.Windows.Forms; // for MessageBox
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi, Pack=1)]
public class DRIS
{
// the first 4 fields are never encrypted
public byte header1; // should be set to "DRIS"
public byte header2;
public byte header3;
public byte header4;
// inputs
public int size; // size of this structure
public int seed1; // seed for data/dris encryption
public int seed2; // as above
// (maybe encrypted from now on)
public int function; // specify only one function
public int flags; // options for the function selected. To use more than one OR them together: OPTION1 | OPTION2...
public uint execs_decrement; // amount by which to dec execs if we use flag: DEC_MANY_EXECS
public int data_crypt_key_num; // number of the key (1-3) that the dongle uses to encrypt or decrypt user data
public int rw_offset; // offset in the dongle data area to read or write data
public int rw_length; // length of data are to read/write/encrypt/decrypt
public IntPtr DoNotUse; // do not use the rw_data_ptr element use the "Data" argument of the DDProtCheck function
[MarshalAs(UnmanagedType.ByValArray, SizeConst=256)] // NB access this field by using alg_licence_name (see below)
private byte[] _alt_licence_name = null; // protection check for different licence instead of this one
public int var_a; // variable values for user algorithm
public int var_b;
public int var_c;
public int var_d;
public int var_e;
public int var_f;
public int var_g;
public int var_h;
public int alg_number; // the number of the user algorithm that you want to execute
// outputs
public int ret_code; // return code from the protection check
public int ext_err; // extended error
public int type; // type of dongle detected. 1 = Pro, 2 = FD
public int model; // model of dongle detected. 1 = Lite, 2 = Plus, 4 = Net 5, 7 = Net Unlimited
public int sdsn; // Software Developer's Serial Number
[MarshalAs(UnmanagedType.ByValArray, SizeConst=12)] // NB access this field by using prodcode (see below)
private byte[] _prodcode = null; // product code (null-terminated)
public uint dongle_number;
public int update_number;
public uint data_area_size; // size of the data area in the dongle detected
public int max_alg_num; // number of algorithms in the dongle detected
public int execs; // executions left: -1 indicates 'no limit'
public int exp_day; // expiry day: -1 indicates 'no limit'
public int exp_month; // expiry month: -1 indicates 'no limit'
public int exp_year; // expiry year: -1 indicates 'no limit'
public uint features; // features value
public int net_users; // maximum number of network users for the dongle detected: -1 indicates 'mo limit'
public int alg_answer; // answer to the user algorithm executed with the given variable values
public uint fd_capacity; // capacity of the data area in FD dongle. Currently fixed at ~10MB but may change in the future.
[MarshalAs(UnmanagedType.ByValArray, SizeConst=128)] // NB access this field by using fd_drive (see below)
private byte[] _fd_drive = null; // fd drive letter (null-terminated)
public int swkey_type; // 0 = no swkey detected, 1 = temporary software key, 2 = demo software key
public int swkey_exp_day; // software key expiry date (if software key detected)
public int swkey_exp_month;
public int swkey_exp_year;
// NB we have to do it this way because we cannot encrypt strings correctly unless they are byte arrays
public string prodcode
{
get
{
StringBuilder sb = new StringBuilder(12);
foreach (byte b in _prodcode)
{
if (b == 0)
return sb.ToString();
else
sb.Append((char)b);
}
return sb.ToString();
}
}
public string fd_drive
{
get
{
StringBuilder sb = new StringBuilder(128);
foreach (byte b in _fd_drive)
{
if (b == 0)
return sb.ToString();
else
sb.Append((char)b);
}
return sb.ToString();
}
}
// NB we have to do it this way because we cannot encrypt strings correctly unless they are byte arrays
public string alt_licence_name
{
set
{
int i;
StringBuilder sb = new StringBuilder(value, 256);
for (i=0; i<sb.Length; i++)
{
_alt_licence_name[i] = (byte)sb[i];
}
_alt_licence_name[i] = 0; // null terminate
}
}
// sets 4 bytes from an integer at the specified offset in a data array
public void Set4Bytes(byte[] data, int offset, int value)
{
data[offset] = (byte)(value & 0xff);
data[offset+1] = (byte)((value >> 8) & 0xff);
data[offset+2] = (byte)((value >> 16) & 0xff);
data[offset+3] = (byte)((value >> 24) & 0xff);
return;
}
// converts to DRIS structure to a byte array (so we can do encryption)
public void DrisToByteArray(DRIS dris, byte[] data)
{
GCHandle MyGC = GCHandle.Alloc(data, GCHandleType.Pinned);
Marshal.StructureToPtr(dris, MyGC.AddrOfPinnedObject(), false);
MyGC.Free();
return;
}
// converts a byte array to the DRIS structure (so we can do encryption)
public void ByteArrayToDris(byte[] data, DRIS dris)
{
GCHandle MyGC = GCHandle.Alloc(data, GCHandleType.Pinned);
Marshal.PtrToStructure(MyGC.AddrOfPinnedObject(), dris);
MyGC.Free();
return;
}
// to make a new instance of this class, initialise every element to a random value and then set the header
public DRIS()
{
Random rnd = new Random();
Byte[] temp = new Byte[Marshal.SizeOf(this)];
rnd.NextBytes(temp);
ByteArrayToDris(temp, this);
this.header1 = (byte)'D';
this.header2 = (byte)'R';
this.header3 = (byte)'I';
this.header4 = (byte)'S';
}
// functions - must specify only one
public const int PROTECTION_CHECK = 1; // checks for dongle, check program params...
public const int EXECUTE_ALGORITHM = 2; // protection check + calculate answer for specified algorithm with specified inputs
public const int WRITE_DATA_AREA = 3; // protection check + writes dongle data area
public const int READ_DATA_AREA = 4; // protection check + reads dongle data area
public const int ENCRYPT_USER_DATA = 5; // protection check + the dongle will encrypt user data
public const int DECRYPT_USER_DATA = 6; // protection check + the dongle will decrypt user data
public const int FAST_PRESENCE_CHECK = 7; // checks for the presence of the correct dongle only with minimal security, no flags allowed.
public const int STOP_NET_USER = 8; // stops a network user (a protection check is NOT performed)
// flags - can specify as many as you like
public const int DEC_ONE_EXEC = 1; // decrement execs by 1
public const int DEC_MANY_EXECS = 2; // decrement execs by number specified in execs_decrement
public const int START_NET_USER = 4; // starts a network user
public const int USE_FUNCTION_ARGUMENT = 16; // use the extra argument in the function for pointers
public const int CHECK_LOCAL_FIRST = 32; // always look in local ports before looking in network ports
public const int CHECK_NETWORK_FIRST = 64; // always look on the network before looking in local ports
public const int USE_ALT_LICENCE_NAME = 128; // use name specified in alt_licence_name instead of the default one
public const int DONT_SET_MAXDAYS_EXPIRY = 256; // if the max days expiry date has not been calculated then do not do it this time
public const int MATCH_DONGLE_NUMBER = 512; // restrict the search to match the dongle number specified in the DRIS
public const int DONT_RETURN_FD_DRIVE = 1024; // if an FD dongle has been detected then don't return the flash drive/mount name in the DRIS
}
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi, Pack=1)]
public struct NU_INFO
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=256)]
public string licenceName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=50)]
public string userName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=256)]
public string computerName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=16)]
public string ipAddress;
}
// 32-bit protection check (loads 32-bit DLL)
class DDProtCheck32
{
[DllImport("dpwin32.dll", CharSet = CharSet.Ansi)]
public static extern int DDProtCheck([In, Out, MarshalAs(UnmanagedType.LPStruct)]DRIS dris, byte[] data);
}
// 64-bit protection check (loads 64-bit DLL)
class DDProtCheck64
{
[DllImport("dpwin64.dll", CharSet = CharSet.Ansi)]
public static extern int DDProtCheck([In, Out, MarshalAs(UnmanagedType.LPStruct)]DRIS dris, byte[] data);
}
// 32-bit get network user info (loads 32-bit DLL)
class DDGetNetUserList32
{
[DllImport("dpwin32.dll", CharSet = CharSet.Ansi)]
public static extern int DDGetNetUserList(string licence_name, out int num_net_users, byte[] nu_info_bytes, int num_info_structs, out int extended_error);
}
// 64-bit get network user info (loads 64-bit DLL)
class DDGetNetUserList64
{
[DllImport("dpwin64.dll", CharSet = CharSet.Ansi)]
public static extern int DDGetNetUserList(string licence_name, out int num_net_users, byte[] nu_info_bytes, int num_info_structs, out int extended_error);
}
// call our API - we only want to load the correct DLL for the bit-ness of the computer. The other DLL may not exist.
class DinkeyPro
{
// calls the DDProtCheck function in the appropriate DLL
public static int DDProtCheck(DRIS dris, byte[] data)
{
int ret_code = -1;
if (IntPtr.Size == 4)
{
try
{
ret_code = DDProtCheck32.DDProtCheck(dris, data);
}
catch (DllNotFoundException)
{
MessageBox.Show("Error! Cannot find dpwin32.dll. This should be in the same folder as DllTest.", "Sample", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
}
else {
try
{
ret_code = DDProtCheck64.DDProtCheck(dris, data);
}
catch (DllNotFoundException)
{
MessageBox.Show("Error! Cannot find dpwin64.dll. This should be in the same folder as DllTest.", "Sample", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
}
return ret_code;
}
public static int DDGetNetUserList(string licence_name, out int num_net_users, out NU_INFO[] nu_info, int num_info_structs, out int extended_error)
{
int ret_code = -1;
int i;
extended_error = num_net_users = 0;
byte[] nu_info_bytes = new byte[num_info_structs * Marshal.SizeOf(typeof(NU_INFO))];
byte[] nu_info_one_struct = new byte[Marshal.SizeOf(typeof(NU_INFO))];
GCHandle MyGC;
nu_info = null;
// call the function and get info as a byte array
if (IntPtr.Size == 4)
ret_code = DDGetNetUserList32.DDGetNetUserList(licence_name, out num_net_users, nu_info_bytes, num_info_structs, out extended_error);
else
ret_code = DDGetNetUserList64.DDGetNetUserList(licence_name, out num_net_users, nu_info_bytes, num_info_structs, out extended_error);
if (ret_code != 0)
return ret_code;
// convert byte array to an array of structs
nu_info = new NU_INFO[num_net_users];
for (i=0; i<num_net_users; i++)
{
Array.Copy(nu_info_bytes, i*Marshal.SizeOf(typeof(NU_INFO)), nu_info_one_struct, 0, Marshal.SizeOf(typeof(NU_INFO)));
MyGC = GCHandle.Alloc(nu_info_one_struct, GCHandleType.Pinned);
nu_info[i] = (NU_INFO)Marshal.PtrToStructure(MyGC.AddrOfPinnedObject(), typeof(NU_INFO));
MyGC.Free();
}
return 0;
}
}