├── .gitignore ├── Directory.Build.Props ├── Program.cs ├── README.md ├── Sharelord.csproj ├── Sharelord.sln ├── bin └── Release │ └── net4.8 │ └── publish │ └── Sharelord.exe └── starlord-dance.gif /.gitignore: -------------------------------------------------------------------------------- 1 | obj/ 2 | bin/ 3 | 4 | 5 | -------------------------------------------------------------------------------- /Directory.Build.Props: -------------------------------------------------------------------------------- 1 | 2 | 3 | false 4 | false 5 | 6 | -------------------------------------------------------------------------------- /Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using System.Security.AccessControl; 4 | using System.Security.Principal; 5 | using System.IO; 6 | 7 | class Program 8 | { 9 | // P/Invoke declarations 10 | [DllImport("Netapi32.dll", CharSet = CharSet.Unicode)] 11 | static extern int NetShareAdd(string servername, int level, ref SHARE_INFO_2 buf, out int parm_err); 12 | 13 | [DllImport("Netapi32.dll", CharSet = CharSet.Unicode)] 14 | static extern int NetShareSetInfo(string servername, string netname, int level, IntPtr buf, out int parm_err); 15 | 16 | [DllImport("Netapi32.dll", CharSet = CharSet.Unicode)] 17 | static extern int NetShareDel(string servername, string netname, int reserved); 18 | 19 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 20 | struct SHARE_INFO_2 21 | { 22 | [MarshalAs(UnmanagedType.LPWStr)] public string shi2_netname; 23 | public uint shi2_type; 24 | [MarshalAs(UnmanagedType.LPWStr)] public string shi2_remark; 25 | public uint shi2_permissions; 26 | public uint shi2_max_uses; 27 | public uint shi2_current_uses; 28 | [MarshalAs(UnmanagedType.LPWStr)] public string shi2_path; 29 | [MarshalAs(UnmanagedType.LPWStr)] public string shi2_passwd; 30 | } 31 | 32 | [StructLayout(LayoutKind.Sequential)] 33 | struct SHARE_INFO_502 34 | { 35 | [MarshalAs(UnmanagedType.LPWStr)] public string shi502_netname; 36 | public uint shi502_type; 37 | [MarshalAs(UnmanagedType.LPWStr)] public string shi502_remark; 38 | public uint shi502_permissions; 39 | public uint shi502_max_uses; 40 | public uint shi502_current_uses; 41 | [MarshalAs(UnmanagedType.LPWStr)] public string shi502_path; 42 | [MarshalAs(UnmanagedType.LPWStr)] public string shi502_passwd; 43 | public uint shi502_reserved; 44 | public IntPtr shi502_security_descriptor; 45 | } 46 | 47 | static void Main(string[] args) 48 | { 49 | if (args.Length == 0 || args[0].ToLower() == "help" || args[0].ToLower() == "--help" || args[0].ToLower() == "-h") 50 | { 51 | ShowDetailedHelp(); 52 | return; 53 | } 54 | 55 | try 56 | { 57 | switch (args[0].ToLower()) 58 | { 59 | case "create": 60 | HandleCreateCommand(args); 61 | break; 62 | case "setace": 63 | if (args.Length != 5) throw new ArgumentException("Invalid number of arguments for setace command."); 64 | SetAce(args[1], args[2], args[3], args[4]); 65 | break; 66 | case "setshareperms": 67 | if (args.Length != 5) throw new ArgumentException("Invalid number of arguments for setshareperms command."); 68 | SetSharePermissions(args[1], args[2], args[3], args[4]); 69 | break; 70 | case "delete": 71 | if (args.Length != 2) throw new ArgumentException("Invalid number of arguments for delete command."); 72 | DeleteShare(args[1]); 73 | break; 74 | default: 75 | throw new ArgumentException("Invalid command."); 76 | } 77 | } 78 | catch (Exception ex) 79 | { 80 | Console.WriteLine($"Error: {ex.Message}"); 81 | PrintUsage(); 82 | } 83 | } 84 | 85 | static void PrintUsage() 86 | { 87 | Console.WriteLine("Usage:"); 88 | Console.WriteLine(" Sharelord.exe [arguments]"); 89 | Console.WriteLine("\nCommands:"); 90 | Console.WriteLine(" create [-r ]"); 91 | Console.WriteLine(" setace "); 92 | Console.WriteLine(" setshareperms "); 93 | Console.WriteLine(" delete "); 94 | Console.WriteLine(" help Show detailed help and list of available permissions"); 95 | Console.WriteLine("\nUse 'Sharelord.exe help' for more detailed information."); 96 | } 97 | 98 | static void ShowDetailedHelp() 99 | { 100 | Console.WriteLine("Sharelord - Detailed Help"); 101 | Console.WriteLine("\nAvailable commands:"); 102 | Console.WriteLine(" create [-r ]"); 103 | Console.WriteLine(" setace "); 104 | Console.WriteLine(" setshareperms "); 105 | Console.WriteLine(" delete "); 106 | Console.WriteLine(" help"); 107 | 108 | Console.WriteLine("\nFile System Rights (for setace command):"); 109 | foreach (FileSystemRights right in Enum.GetValues(typeof(FileSystemRights))) 110 | { 111 | Console.WriteLine($" {right}"); 112 | } 113 | 114 | Console.WriteLine("\nAccess Control Types:"); 115 | Console.WriteLine(" Allow"); 116 | Console.WriteLine(" Deny"); 117 | 118 | Console.WriteLine("\nShare Permissions (for setshareperms command):"); 119 | Console.WriteLine(" Read - Users can view file and subfolder names, read data, and run programs"); 120 | Console.WriteLine(" Change - Users have Read permissions plus the ability to create, change, and delete files and subfolders"); 121 | Console.WriteLine(" FullControl - Users have Change permissions plus the ability to change permissions and take ownership"); 122 | 123 | Console.WriteLine("\nExamples:"); 124 | Console.WriteLine(" Sharelord.exe create C:\\SharedFolder MyShare -r \"Shared folder for team\""); 125 | Console.WriteLine(" Sharelord.exe setace C:\\SharedFolder Domain\\User Modify Allow"); 126 | Console.WriteLine(" Sharelord.exe setshareperms MyShare Domain\\User Change Allow"); 127 | Console.WriteLine(" Sharelord.exe delete MyShare"); 128 | } 129 | 130 | static void HandleCreateCommand(string[] args) 131 | { 132 | if (args.Length < 3) 133 | { 134 | throw new ArgumentException("Invalid number of arguments for create command."); 135 | } 136 | 137 | string directory = args[1]; 138 | string shareName = args[2]; 139 | string remark = null; 140 | 141 | // Check for optional remark flag 142 | for (int i = 3; i < args.Length; i++) 143 | { 144 | if (args[i] == "-r" && i + 1 < args.Length) 145 | { 146 | remark = args[i + 1]; 147 | break; 148 | } 149 | } 150 | 151 | CreateShare(directory, shareName, remark); 152 | } 153 | 154 | static void CreateShare(string directory, string shareName, string remark) 155 | { 156 | if (!Directory.Exists(directory)) 157 | { 158 | throw new DirectoryNotFoundException($"The directory '{directory}' does not exist."); 159 | } 160 | 161 | SHARE_INFO_2 shareInfo = new SHARE_INFO_2 162 | { 163 | shi2_netname = shareName, 164 | shi2_type = 0, // Disk share 165 | shi2_remark = remark, 166 | shi2_permissions = 0, // Use NT security 167 | shi2_max_uses = unchecked((uint)-1), // Maximum allowed 168 | shi2_current_uses = 0, 169 | shi2_path = directory, 170 | shi2_passwd = null 171 | }; 172 | 173 | int parmErr = 0; 174 | int result = NetShareAdd(null, 2, ref shareInfo, out parmErr); 175 | 176 | if (result != 0) 177 | { 178 | throw new Exception($"Failed to create share. Error code: {result}, Parameter Error: {parmErr}"); 179 | } 180 | 181 | Console.WriteLine($"Share '{shareName}' created successfully for directory '{directory}'."); 182 | if (!string.IsNullOrEmpty(remark)) 183 | { 184 | Console.WriteLine($"Remark: {remark}"); 185 | } 186 | } 187 | 188 | static void SetAce(string directory, string username, string rights, string type) 189 | { 190 | FileSystemRights fsr = (FileSystemRights)Enum.Parse(typeof(FileSystemRights), rights); 191 | AccessControlType act = (AccessControlType)Enum.Parse(typeof(AccessControlType), type); 192 | 193 | DirectoryInfo dirInfo = new DirectoryInfo(directory); 194 | DirectorySecurity dirSecurity = dirInfo.GetAccessControl(); 195 | 196 | dirSecurity.AddAccessRule(new FileSystemAccessRule(username, fsr, 197 | InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit, 198 | PropagationFlags.None, act)); 199 | 200 | dirInfo.SetAccessControl(dirSecurity); 201 | 202 | Console.WriteLine($"ACE set for {username} on {directory}"); 203 | } 204 | 205 | static void SetSharePermissions(string shareName, string username, string permissions, string type) 206 | { 207 | NTAccount account = new NTAccount(username); 208 | SecurityIdentifier sid = (SecurityIdentifier)account.Translate(typeof(SecurityIdentifier)); 209 | 210 | uint permissionsMask = (uint)Enum.Parse(typeof(FileSystemRights), permissions); 211 | string sdString = $"D:(A;;{permissionsMask:X};;;{sid.Value})"; 212 | 213 | RawSecurityDescriptor rsd = new RawSecurityDescriptor(sdString); 214 | byte[] binarySD = new byte[rsd.BinaryLength]; 215 | rsd.GetBinaryForm(binarySD, 0); 216 | 217 | IntPtr securityDescriptor = Marshal.AllocHGlobal(binarySD.Length); 218 | Marshal.Copy(binarySD, 0, securityDescriptor, binarySD.Length); 219 | 220 | SHARE_INFO_502 shareInfo = new SHARE_INFO_502 221 | { 222 | shi502_netname = shareName, 223 | shi502_type = 0, 224 | shi502_remark = null, 225 | shi502_permissions = 0, 226 | shi502_max_uses = unchecked((uint)-1), 227 | shi502_current_uses = 0, 228 | shi502_path = null, 229 | shi502_passwd = null, 230 | shi502_reserved = 0, 231 | shi502_security_descriptor = securityDescriptor 232 | }; 233 | 234 | IntPtr pShareInfo = Marshal.AllocHGlobal(Marshal.SizeOf(shareInfo)); 235 | Marshal.StructureToPtr(shareInfo, pShareInfo, false); 236 | 237 | try 238 | { 239 | int parmErr = 0; 240 | int result = NetShareSetInfo(null, shareName, 502, pShareInfo, out parmErr); 241 | if (result != 0) 242 | { 243 | throw new Exception($"Failed to set share permissions. Error code: {result}"); 244 | } 245 | 246 | Console.WriteLine($"Share permissions set for {username} on {shareName}"); 247 | } 248 | finally 249 | { 250 | Marshal.FreeHGlobal(securityDescriptor); 251 | Marshal.FreeHGlobal(pShareInfo); 252 | } 253 | } 254 | 255 | static void DeleteShare(string shareName) 256 | { 257 | int result = NetShareDel(null, shareName, 0); 258 | if (result == 0) 259 | { 260 | Console.WriteLine($"Share '{shareName}' deleted successfully."); 261 | } 262 | else 263 | { 264 | throw new Exception($"Failed to delete share. Error code: {result}"); 265 | } 266 | } 267 | } 268 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Sharelord (lowercase l) 2 | ![](https://github.com/NocteDefensor/ShareLord/blob/main/starlord-dance.gif) 3 | 4 | .NET Assembly to learn how to interact with Win32 APIs to create network shares, delete shares, and set share perms. It uses .NET methods to set ACE. Will eventually switch all to more directly use Win32 APIs. Currently using PInvoke. I hope to switch to DInvoke soon when I figure out an memory access violation i'm running into. Help with DInvoke would be greatly appreciated. 5 | --- 6 | Sharelord is a command-line tool for managing Windows shared folders and their permissions. 7 | 8 | ## Features 9 | 10 | - Create and delete shared folders 11 | - Set file system access control entries (ACEs) 12 | - Set share-level permissions 13 | 14 | ## Usage 15 | 16 | Run `Sharelord.exe --help` for detailed information on available commands and options. 17 | 18 | Basic syntax: 19 | 20 | ``` 21 | Sharelord.exe [options] 22 | ``` 23 | 24 | ## Examples 25 | 26 | Create a shared folder: 27 | ``` 28 | Sharelord.exe create C:\SharedFolder MyShare -r "Shared folder for team" 29 | ``` 30 | 31 | Set file system permissions: 32 | ``` 33 | Sharelord.exe setace C:\SharedFolder Domain\User Modify Allow 34 | ``` 35 | 36 | Set share-level permissions: 37 | ``` 38 | Sharelord.exe setshareperms MyShare Domain\User Change Allow 39 | ``` 40 | 41 | Delete a share: 42 | ``` 43 | Sharelord.exe delete MyShare 44 | ``` 45 | 46 | ## Note 47 | 48 | For a full list of commands, options, and permissions, refer to the built-in help menu by running `Sharelord.exe --help`. 49 | 50 | ## Build Instructions 51 | 52 | This project is a .NET application targeting .NET Framework 4.8. 53 | 54 | ### Prerequisites 55 | 56 | To build and run this project, you'll need: 57 | 58 | - [Visual Studio Code](https://code.visualstudio.com/) 59 | - [.NET Framework 4.8 Developer Pack](https://dotnet.microsoft.com/download/dotnet-framework/net48) 60 | - [C# extension for Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.csharp) 61 | 62 | ### Dependencies 63 | 64 | The project has the following dependencies: 65 | 66 | - System.IO.FileSystem.AccessControl (5.0.0) 67 | - System.Security.AccessControl (6.0.1) 68 | - System.Security.Principal.Windows (5.0.0) 69 | 70 | 71 | ### Building the Project 72 | 73 | 1. Open the project folder in Visual Studio Code. 74 | 2. Open the integrated terminal in VS Code (View > Terminal). 75 | 3. Run the following command to build the project: 76 | 77 | ``` 78 | dotnet build 79 | ``` 80 | 81 | 4. If you want to create a release build, use: 82 | 83 | ``` 84 | dotnet build -c Release 85 | ``` 86 | 87 | ### Notes 88 | 89 | - The project is configured to use the latest C# language version. 90 | - Unsafe blocks are allowed in the code. 91 | - In Release configuration, debug symbols are not generated. 92 | 93 | For more detailed information about the project structure and configuration, refer to the `.csproj` file. 94 | 95 | ## References 96 | - https://github.com/TheWover/DInvoke 97 | - https://github.com/rasta-mouse/DInvoke 98 | - https://www.pinvoke.net/default.aspx/netapi32/_ContentBaseDefinition.html 99 | - https://learn.microsoft.com/en-us/windows/win32/api/lmshare/nf-lmshare-netshareadd 100 | - https://learn.microsoft.com/en-us/windows/win32/api/lmshare/nf-lmshare-netsharedel 101 | - https://learn.microsoft.com/en-us/windows/win32/api/lmshare/nf-lmshare-netsharesetinfo 102 | - https://learn.microsoft.com/en-us/windows/win32/api/lmshare/ns-lmshare-share_info_2 103 | - https://learn.microsoft.com/en-us/windows/win32/api/lmshare/ns-lmshare-share_info_502 104 | -------------------------------------------------------------------------------- /Sharelord.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | net4.8 11 | Exe 12 | latest 13 | true 14 | false 15 | annotations 16 | true 17 | false 18 | 19 | 20 | 21 | none 22 | false 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Sharelord.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.5.002.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sharelord", "Sharelord.csproj", "{0D00E441-BE4C-47DF-A57E-522102531FC0}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {0D00E441-BE4C-47DF-A57E-522102531FC0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {0D00E441-BE4C-47DF-A57E-522102531FC0}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {0D00E441-BE4C-47DF-A57E-522102531FC0}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {0D00E441-BE4C-47DF-A57E-522102531FC0}.Release|Any CPU.Build.0 = Release|Any CPU 18 | {D8387AAA-678F-4814-A6D4-F95319814BC0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 19 | {D8387AAA-678F-4814-A6D4-F95319814BC0}.Debug|Any CPU.Build.0 = Debug|Any CPU 20 | {D8387AAA-678F-4814-A6D4-F95319814BC0}.Release|Any CPU.ActiveCfg = Release|Any CPU 21 | {D8387AAA-678F-4814-A6D4-F95319814BC0}.Release|Any CPU.Build.0 = Release|Any CPU 22 | {2B484232-9B5E-43C5-A4F9-9B3E652EAD3D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 23 | {2B484232-9B5E-43C5-A4F9-9B3E652EAD3D}.Debug|Any CPU.Build.0 = Debug|Any CPU 24 | {2B484232-9B5E-43C5-A4F9-9B3E652EAD3D}.Release|Any CPU.ActiveCfg = Release|Any CPU 25 | {2B484232-9B5E-43C5-A4F9-9B3E652EAD3D}.Release|Any CPU.Build.0 = Release|Any CPU 26 | {321AAE29-29C3-4FF0-9159-313584A8E1D7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 27 | {321AAE29-29C3-4FF0-9159-313584A8E1D7}.Debug|Any CPU.Build.0 = Debug|Any CPU 28 | {321AAE29-29C3-4FF0-9159-313584A8E1D7}.Release|Any CPU.ActiveCfg = Release|Any CPU 29 | {321AAE29-29C3-4FF0-9159-313584A8E1D7}.Release|Any CPU.Build.0 = Release|Any CPU 30 | EndGlobalSection 31 | GlobalSection(SolutionProperties) = preSolution 32 | HideSolutionNode = FALSE 33 | EndGlobalSection 34 | GlobalSection(ExtensibilityGlobals) = postSolution 35 | SolutionGuid = {73B18981-8F02-4FDD-B21F-D41182516ECB} 36 | EndGlobalSection 37 | EndGlobal 38 | -------------------------------------------------------------------------------- /bin/Release/net4.8/publish/Sharelord.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NocteDefensor/Sharelord/7272c55a945e9b9cce5734b0c14ea36e3a3bf7a5/bin/Release/net4.8/publish/Sharelord.exe -------------------------------------------------------------------------------- /starlord-dance.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NocteDefensor/Sharelord/7272c55a945e9b9cce5734b0c14ea36e3a3bf7a5/starlord-dance.gif --------------------------------------------------------------------------------