Skip to content

Commit

Permalink
Added admin privileges elevation
Browse files Browse the repository at this point in the history
  • Loading branch information
mas6y6 committed Dec 13, 2024
1 parent 5d525ff commit 283f301
Show file tree
Hide file tree
Showing 6 changed files with 204 additions and 2 deletions.
37 changes: 37 additions & 0 deletions cipher/elevate/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import sys, platform, os, ctypes

def is_root():
system = platform.system()
if system in ["Linux", "Darwin"]:
try:
return os.getuid() == 0
except AttributeError:
return False
elif system == "Windows":
try:
return ctypes.windll.shell32.IsUserAnAdmin() != 0
except AttributeError:
return False
else:
raise NotImplementedError(f"Unsupported OS: {system}")

def elevate(show_console=True, graphical=True):
"""
Re-launch the current process with root/admin privileges
When run as root, this function does nothing.
When not run as root, this function replaces the current process (Linux,
macOS) or creates a child process, waits, and exits (Windows).
:param show_console: (Windows only) if True, show a new console for the
child process. Ignored on Linux / macOS.
:param graphical: (Linux / macOS only) if True, attempt to use graphical
programs (gksudo, etc). Ignored on Windows.
"""
if sys.platform.startswith("win"):
from elevate.windows import elevate
else:
from elevate.posix import elevate
elevate(show_console, graphical)

Binary file not shown.
54 changes: 54 additions & 0 deletions cipher/elevate/posix.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import errno
import os
import sys
try:
from shlex import quote
except ImportError:
from pipes import quote


def quote_shell(args):
return " ".join(quote(arg) for arg in args)


def quote_applescript(string):
charmap = {
"\n": "\\n",
"\r": "\\r",
"\t": "\\t",
"\"": "\\\"",
"\\": "\\\\",
}
return '"%s"' % "".join(charmap.get(char, char) for char in string)


def elevate(show_console=True, graphical=True):
if os.getuid() == 0:
return

args = [sys.executable] + sys.argv
commands = []

if graphical:
if sys.platform.startswith("darwin"):
commands.append([
"osascript",
"-e",
"do shell script %s "
"with administrator privileges "
"without altering line endings"
% quote_applescript(quote_shell(args))])

if sys.platform.startswith("linux") and os.environ.get("DISPLAY"):
commands.append(["pkexec"] + args)
commands.append(["gksudo"] + args)
commands.append(["kdesudo"] + args)

commands.append(["sudo"] + args)

for args in commands:
try:
os.execlp(args[0], *args)
except OSError as e:
if e.errno != errno.ENOENT or args[0] == "sudo":
raise
89 changes: 89 additions & 0 deletions cipher/elevate/windows.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import ctypes
from ctypes import POINTER, c_ulong, c_char_p, c_int, c_void_p
from ctypes.wintypes import HANDLE, BOOL, DWORD, HWND, HINSTANCE, HKEY
from ctypes import windll
import subprocess
import sys

# Constant defintions


SEE_MASK_NOCLOSEPROCESS = 0x00000040
SEE_MASK_NO_CONSOLE = 0x00008000


# Type definitions

PHANDLE = ctypes.POINTER(HANDLE)
PDWORD = ctypes.POINTER(DWORD)


class ShellExecuteInfo(ctypes.Structure):
_fields_ = [
('cbSize', DWORD),
('fMask', c_ulong),
('hwnd', HWND),
('lpVerb', c_char_p),
('lpFile', c_char_p),
('lpParameters', c_char_p),
('lpDirectory', c_char_p),
('nShow', c_int),
('hInstApp', HINSTANCE),
('lpIDList', c_void_p),
('lpClass', c_char_p),
('hKeyClass', HKEY),
('dwHotKey', DWORD),
('hIcon', HANDLE),
('hProcess', HANDLE)]

def __init__(self, **kw):
super(ShellExecuteInfo, self).__init__()
self.cbSize = ctypes.sizeof(self)
for field_name, field_value in kw.items():
setattr(self, field_name, field_value)


PShellExecuteInfo = POINTER(ShellExecuteInfo)


# Function definitions

ShellExecuteEx = windll.shell32.ShellExecuteExA
ShellExecuteEx.argtypes = (PShellExecuteInfo, )
ShellExecuteEx.restype = BOOL

WaitForSingleObject = windll.kernel32.WaitForSingleObject
WaitForSingleObject.argtypes = (HANDLE, DWORD)
WaitForSingleObject.restype = DWORD

CloseHandle = windll.kernel32.CloseHandle
CloseHandle.argtypes = (HANDLE, )
CloseHandle.restype = BOOL


# At last, the actual implementation!

def elevate(show_console=True, graphical=True):
if windll.shell32.IsUserAnAdmin():
return

params = ShellExecuteInfo(
fMask=SEE_MASK_NOCLOSEPROCESS | SEE_MASK_NO_CONSOLE,
hwnd=None,
lpVerb=b'runas',
lpFile=sys.executable.encode('cp1252'),
lpParameters=subprocess.list2cmdline(sys.argv).encode('cp1252'),
nShow=int(show_console))

if not ShellExecuteEx(ctypes.byref(params)):
raise ctypes.WinError()

handle = params.hProcess
ret = DWORD()
WaitForSingleObject(handle, -1)

if windll.kernel32.GetExitCodeProcess(handle, ctypes.byref(ret)) == 0:
raise ctypes.WinError()

CloseHandle(handle)
sys.exit(ret.value)
24 changes: 23 additions & 1 deletion main.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import argparse
import ctypes
import os
import socket
import sys
Expand Down Expand Up @@ -110,6 +111,7 @@ def get_resource_path(relative_path):
import cipher.network
from cipher.parsers import ArgumentParser, ConfigParser
import cipher.api
from cipher.elevate import elevate, is_root

# variables
version = 1
Expand Down Expand Up @@ -145,7 +147,7 @@ def printerror(msg):
parser = argparse.ArgumentParser()
parser.add_argument("--debug",action="store_true",help="Enables debug mode")
parser.add_argument("--startdir",action="store",help="Overrides the cache directory")

parser.add_argument("--sudo",action="store_true",help="Enables sudo mode")
executeargs = parser.parse_args()

def is_running_in_appdata():
Expand Down Expand Up @@ -318,6 +320,22 @@ def executables(argsraw):
tab.add_row(i)
console.print(tab)

@api.command()
def sudomode(argsraw):
parser = ArgumentParser(api, description="Elevates permissions to admin permissions for CipherOS")

args = parser.parse_args(argsraw)

if parser.help_flag:
return None

if not is_root():
console.print("Entering Sudomode",style="bright_red")
console.print("Acquiring Admin privileges (This may open a password prompt)",style="bright_red")
elevate(graphical=False)
else:
printerror("Error: Admin permissions already acquired")

@api.command(alias=["scn", "netscan"])
def scannet(argsraw):
parser = ArgumentParser(api, description="Scan your network for devices")
Expand Down Expand Up @@ -800,6 +818,8 @@ def remove(argsraw):

if debugmode:
console.print("Starting CipherOS in [purple]debug mode[/purple]")
if is_root():
console.print("Admin privileges detected starting as admin",style="bright_magenta")
api.debug = True
@api.command()
def arbc(argsraw):
Expand Down Expand Up @@ -841,6 +861,8 @@ def vdump(argsraw):
print(f"vdump encountered an error: {e}")
else:
console.print("Starting CipherOS")
if is_root():
console.print("Admin privileges detected starting as admin",style="bright_magenta")

if not len(os.listdir(os.path.join(api.starterdir,"plugins"))) == 0:
for i in os.listdir(os.path.join(api.starterdir,"plugins")):
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@ ping3
netifaces
markdown
rich
hostprobe
hostprobe

0 comments on commit 283f301

Please sign in to comment.