Create a (cyphered) keyfile with your logon

Share your advanced PureBasic knowledge/code with the community.
Anden
Enthusiast
Enthusiast
Posts: 135
Joined: Mon Jul 21, 2003 7:23 am
Contact:

Create a (cyphered) keyfile with your logon

Post by Anden »

Code updated for 5.20+

As promised, here's the code:
(Uses a RC4 algo from this forum, slightly optimized 4 performance)

Create a (cyphered) keyfile with your logon credentials first, then start the programs with changed user rights.

Code: Select all

Enumeration
  #USER_PRIV_GUEST
  #USER_PRIV_USER
  #USER_PRIV_ADMIN
EndEnumeration

#NERR_SUCCESS = 0

Procedure RC4Cipher(Mem, memLen)
  Dim S.w(255)  
  Dim K.w(255) 
  RC4Key.s = "YourKeyPhraseHere!" 
  i = 0 : t = 0 : x = 0 : temp.w = 0 : y.w = 0 : j = 1 
  keylen = Len(RC4Key)
  For i = 0 To 255        
    S(i) = i
    If (j > keylen) : j = 1 : EndIf   
    K(i) = Asc(Mid(RC4Key, j, 1)) 
    j = j + 1   
  Next i      
  j = 0 
  For i = 0 To 255   
    j = (j + S(i) + K(i)) & 255
    temp = S(i)
    S(i) = S(j)
    S(j) = temp
  Next i
  i = 0 : j = 0 
  For x = 0 To memLen-1
    i = (i + 1) & 255
    j = (j + S(i)) & 255
    temp = S(i)
    S(i) = S(j)
    S(j) = temp
    t = (S(i) + (S(j) & 255)) & 255
    y = S(t)
    PokeB(Mem+x, PeekB(Mem+x)!y)
  Next x 
  ProcedureReturn Mem
EndProcedure

Procedure.s ShowError()
  err = GetLastError_()
  If (err)
    *memBuffer = AllocateMemory (255)
    FormatMessage_(#FORMAT_MESSAGE_FROM_SYSTEM, #Null, err, 0, *memBuffer, 255, #Null)
    err$ = PeekS(*memBuffer)
    FreeMemory(*memBuffer)
    ProcedureReturn err$ 
  EndIf
EndProcedure

Procedure.b IsAdmin()
  Result.b = #False
  ui3.USER_INFO_3
  usr$ = Space(256)
  nsize = Len(usr$)
  GetUserName_(@usr$, @nsize)
  w_usr$ = Space(512)
  MultiByteToWideChar_(#CP_ACP, #MB_PRECOMPOSED, @usr$, -1, @w_usr$, Len(w_usr$)) 
  If (NetUserGetInfo_(#Null, @w_usr$, 3, @lpBuf) = #NERR_SUCCESS)
    CopyMemory(lpBuf, @ui3, SizeOf(ui3))
    If (ui3\usri3_priv = #USER_PRIV_ADMIN) : Result = #True : EndIf
    NetApiBufferFree_(lpBuf)
  EndIf
  ProcedureReturn Result
EndProcedure

Procedure ShowUsage()
  dumstr1.s = "2A-RunAs.exe <progname>"+Chr(10)+"Start program with user credentials from keyfile."
  dumstr2.s = "2A-RunAs.exe -k <logon> <passwd>"+Chr(10)+"Create keyfile for supplied user credentials."
  MessageRequester("2A-RunAs Arguments", dumstr1+Chr(10)+Chr(10)+dumstr2, #PB_MessageRequester_Ok|#MB_ICONINFORMATION) 
EndProcedure

Procedure WriteKeyFile(cpass.s, cname.s)
  If (cname > "" And cpass > "") 
    If (CreateFile(1, "2A-RunAs.dat"))
      *cypherBuffer = AllocateMemory(516)
      strlen = Len(cname)
      CopyMemory(@cname, *cypherBuffer, strlen)
      RC4Cipher(*cypherBuffer, strlen) 
      WriteWord(1, strlen)
      WriteData(1, *cypherBuffer, strlen)
      strlen = Len(cpass)
      CopyMemory(@cpass, *cypherBuffer, strlen)
      RC4Cipher(*cypherBuffer, strlen) 
      WriteWord(1, strlen)
      WriteData(1, *cypherBuffer, strlen)
      CloseFile(1)
      FreeMemory(*cypherBuffer)
      MessageRequester("2A-RunAs Status", "Keyfile has been generated and saved.", #PB_MessageRequester_Ok|#MB_ICONINFORMATION)
    Else
      MessageRequester("I/O Problem", "Could not write keyfile!", #PB_MessageRequester_Ok|#MB_ICONERROR)
    EndIf
  Else
    ShowUsage()
  EndIf 
EndProcedure

Procedure ReadKeyFile(*cname, *cpass)
  If (ReadFile(1, "2A-RunAs.dat"))
    *cypherBuffer = AllocateMemory(516)
    strlen = ReadWord(1)
    ReadData(1,*cypherBuffer, strlen)
    RC4Cipher(*cypherBuffer, strlen) 
    CopyMemory(*cypherBuffer, *cname, strlen)
    PokeB(*cname+strlen, 0)
    strlen = ReadWord(1)
    ReadData(1,*cypherBuffer, strlen)
    RC4Cipher(*cypherBuffer, strlen) 
    CopyMemory(*cypherBuffer, *cpass, strlen)
    PokeB(*cpass+strlen, 0)
    CloseFile(1)
    FreeMemory(*cypherBuffer)
  Else
    MessageRequester("I/O Problem", "Could not read keyfile!", #PB_MessageRequester_Ok|#MB_ICONERROR)
    End
  EndIf 
EndProcedure

Procedure SpawnProcess(cname.s, cpass.s, mycomm.s) 
  w_cname.s = Space(512)
  MultiByteToWideChar_(#CP_ACP, #MB_PRECOMPOSED, @cname, -1, @w_cname, Len(w_cname)) 
  w_cpass.s = Space(512)
  MultiByteToWideChar_(#CP_ACP, #MB_PRECOMPOSED, @cpass, -1, @w_cpass, Len(w_cpass)) 
  cdom.s = Space(256)
  nsize.w = Len(cdom)
  GetComputerName_(@cdom, @nsize)
  w_cdom.s = Space(512)
  MultiByteToWideChar_(#CP_ACP, #MB_PRECOMPOSED, @cdom, -1, @w_cdom, Len(w_cdom)) 
  w_ccomm.s = Space(512)
  MultiByteToWideChar_(#CP_ACP, #MB_PRECOMPOSED, @mycomm, -1, @w_ccomm, Len(w_ccomm)) 
  cpath.s = GetPathPart(mycomm)
  w_cpath.s = Space(512)
  MultiByteToWideChar_(#CP_ACP, #MB_PRECOMPOSED, @cpath, -1, @w_cpath, Len(w_cpath)) 
  StartInfo.STARTUPINFO
  StartInfo\cb = SizeOf(StartInfo)
  StartInfo\dwFlags = 0
  ProcessInfo.PROCESS_INFORMATION
  flags = #CREATE_NEW_CONSOLE|#CREATE_NEW_PROCESS_GROUP|#CREATE_DEFAULT_ERROR_MODE
  OpenLibrary(0, "advapi32.dll")
  CallFunction(0, "CreateProcessWithLogonW", @w_cname, @w_cdom, @w_cpass, 0, @w_ccomm, #Null, flags, #Null, @w_cpath, @StartInfo, @ProcessInfo) 
  errstr.s = ShowError()
  If (Len(errstr))
    MessageRequester("2A-RunAs Error", errstr, #PB_MessageRequester_Ok|#MB_ICONERROR)
  EndIf
  CloseLibrary(0)
  CloseHandle_(ProcessInfo\hThread) 
  CloseHandle_(ProcessInfo\hProcess) 
EndProcedure

progexe.s = Trim(ProgramParameter())
Select LCase(progexe)
  Case ""
    ShowUsage()
  Case "-k"
    WriteKeyFile(ProgramParameter(), ProgramParameter()) ;3rd and 2nd parameter (parsed from right to left)
  Default
    If (GetExtensionPart(progexe) = "")
      progexe = progexe + ".exe"
    EndIf
    If (IsAdmin() = #True)
      If (RunProgram(progexe, "", GetPathPart(progexe)) = 0)
        MessageRequester("2A-RunAs Error", "Even an admin could not start"+Chr(10)+Chr(10)+progexe , #PB_MessageRequester_Ok|#MB_ICONERROR) 
      EndIf
    Else 
      cname.s = Space(256)
      cpass.s = Space(256)
      ReadKeyFile(@cname, @cpass)
      SpawnProcess(cname, cpass, progexe)
    EndIf
EndSelect
End