Is it possible to duplicate the following credential process in VB.NET? - windows

Solution (kinda):
Turns out this impersonation with .NET's security only allows application-level access. Since the COM object is at the system level, the impersonated user still cannot instantiate it. I figured this out by right-clicking the executable and selecting "Run As...", the program functioned fine. I found out that launches the program with system access (assuming the user you are running it with has those credentials). Now I am in the process of creating an external program that will launch this application using this method.
Thanks for the tips :D
I have a windows XP installation on a virtual machine. It is part of my domain, but the logged in user is a local user only. Obviously, if I try to access a network share it will prompt for a user/password:
The program I am testing out on the virtual machine uses a COM object to interface with data from another program. If I do not impersonate, I get errors because I do not have the proper credentials.
I did some research into the matter and found a number of websites that had a decent amount of VB.NET information. The problem I am having with the code I wrote is I can access the network resources, but I cannot instantiate the COM object.
If I fill and submit the credential prompt (above) before attempting to instantiate it, it works fine. That leads me to believe there must be something that the WinXP credential prompt is doing that I am not. Below is the code I am using for Impersonation:
Public Sub BeginImpersonation()
Const LOGON32_PROVIDER_DEFAULT As Integer = 0
Const LOGON32_LOGON_INTERACTIVE As Integer = 2
Const SecurityImpersonation As Integer = 2
Dim win32ErrorNumber As Integer
_tokenHandle = IntPtr.Zero
_dupeTokenHandle = IntPtr.Zero
If Not LogonUser(_username, _domainname, _password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, _tokenHandle) Then
win32ErrorNumber = System.Runtime.InteropServices.Marshal.GetLastWin32Error()
Throw New ImpersonationException(win32ErrorNumber, GetErrorMessage(win32ErrorNumber), _username, _domainname)
End If
If Not DuplicateToken(_tokenHandle, SecurityImpersonation, _dupeTokenHandle) Then
win32ErrorNumber = System.Runtime.InteropServices.Marshal.GetLastWin32Error()
CloseHandle(_tokenHandle)
Throw New ImpersonationException(win32ErrorNumber, "Unable to duplicate token!", _username, _domainname)
End If
Dim newId As New System.Security.Principal.WindowsIdentity(_dupeTokenHandle)
_impersonatedUser = newId.Impersonate()
_impersonating = True
End Sub
I have also tried sending different flags to the impersonator method, but nothing seems to be working. Here are the different flags I found:
Enum LOGON32_LOGON
INTERACTIVE = 2
NETWORK = 3
BATCH = 4
SERVICE = 5
UNLOCK = 7
NETWORK_CLEARTEXT = 8
NEW_CREDENTIALS = 9
End Enum
Enum LOGON32_PROVIDER
[DEFAULT] = 0
WINNT35 = 1
WINNT40 = 2
WINNT50 = 3
End Enum
Enum SECURITY_LEVEL
Anonymous = 0
Identification = 1
Impersonation = 2
Delegation = 3
End Enum

I have run into this before, and used two different soloution - the easiest was using a third party app: TqcRunas: http://www.quimeras.com/Products/products.asp which allows you to package the required creentials in an encrypted file. However is a pain if the password is forced to expire.
The other solution that I have used is to call a new process with alternative credentials:
Dim myProcessStartInfo As ProcessStartInfo = New ProcessStartInfo
With myProcessStartInfo
.FileName = "file path and name"
.Domain = "domainname"
.UserName = "username"
'password needs to be a SerureString
Using NewPassword As New Security.SecureString
With NewPassword
For Each c As Char In "password".ToCharArray
.AppendChar(c)
Next c
.MakeReadOnly()
End With
.Password = NewPassword.Copy
End Using
'UseShellExecute must be false for impersonated process
.UseShellExecute = False
End With
Using Process As New System.Diagnostics.Process
With Process
.StartInfo = myProcessStartInfo
.Start()
End With
End Using

With your definitions, I use
LogonUser(_username, _domainname, _password, LOGON32_LOGON_NEW_CREDENTIALS, LOGON32_PROVIDER_WINNT50, _tokenHandle)
in my code that is authenticating across the network. I am impersonating a local user on the remote box, as you are. It was so long ago that I don't remember the rationale for using these values, however.

I do a similar thing to map network drives for copying files between machines. I didn't write the code but it's pretty much the same as yours, except for two things:
After the Impersonate method returns I close both tokens using the CloseHandle routine, before I exit my impersonator method.
At the top of the impersonator the first thing that happens is a call to RevertToSelf, presumably to cancel any previous impersonation.
I don't know if they would make a difference but it's worth a try. Here are the relevant declarations:
Declare Auto Function CloseHandle Lib "kernel32.dll" (ByVal handle As IntPtr) As Long
Declare Auto Function RevertToSelf Lib "advapi32.dll" () As Long

Related

How to asdd call attrs. after the call droped just like mark done button?

I am able to add call attrs using 'Genesyslab.Platform.Voice.Protocols.TServer.Requests.Userdata.RequestAttachUserData' when the call is online but how to do when the call is dropped?
I found this in WDE
void SelectDispositionCodeSetAttachedData(string dispositionCodeValueName);
//
// Summary:
// Update or add the keys of the specificed KeyValueCollection in the attached data
// of the interaction . The current list of attached data can then be retrieved
// using GetAttachedData. If the interaction media type is 'voice' or 'instant message'
// and the interaction is not released the added/updated values are immediately
// committed to T/SIP Server. If the interaction media type is 'voice' or 'instant
// message' and the interaction is released the added/updated values are sent to
// T/SIP Server as a UserEvent when the interaction is marked done (programmatic?aly
// or by Agent). If it is an eServices interaction (e-mail, chat, etc.) and the
// interaction is still handled by the agent the added/updated values are immediately
// committed to Interaction Server. After e-Services interaction is released, no
// further programmatical update is committed to Interaction Server. For all interaction
// types any attached data programmatical update applied after interaction release
// is not reflected in UI controls such as 'Case information'.
This is my code:
Genesyslab.Platform.Commons.Collections.KeyValueCollection keyValueCollectionUpDate = new Genesyslab.Platform.Commons.Collections.KeyValueCollection();
keyValueCollectionUpDate.Add("Business Result", "Platform: Business Result");
keyValueCollectionUpDate.Add("StrAttribute1", "AttachedData.Business Result"); RequestAttachUserData requestAttachUserData= RequestAttachUserData.Create("7012", GetConnectionID(ExtractedArtributes[1][0].Value.ToString()), keyValueCollectionUpDate); IMessage respondingEvent2=tserverProtocol.Request(requestAttachUserData);
Need to add call attts after the call is dropped
You can't update attached data when the call is dropped.
I do a workaround by using WDE itself to attach data when agent clicks 'mark done' in WDE custom command.
The way to attach data to voice calls after disconnect, is to send a UserEvent. This does require the AfterCallWork state to be enabled in your environment. You have already mentioned understanding how to insert Commands into the Command Chain. This example Execute function of a command can be inserted into the "BundleClose" Command Chain, prior to the "Close" Command.
This sample is in VB, apologies, but I guess you can easily convert to c#.
Public Function Execute(ByVal parameters As IDictionary(Of String, Object), ByVal progress As IProgressUpdater) As Boolean Implements IElementOfCommand.Execute
' To go to the main thread
If Application.Current.Dispatcher IsNot Nothing AndAlso Not Application.Current.Dispatcher.CheckAccess() Then
Dim result As Object = Application.Current.Dispatcher.Invoke(DispatcherPriority.Send, New ExecuteDelegate(AddressOf Execute), parameters, progress)
Return CBool(result)
Else
Dim interactionsBundle As IInteractionsBundle = Nothing
Dim interaction As IInteraction = Nothing
interactionsBundle = parameters("CommandParameter")
interaction = interactionsBundle.MainInteraction
Dim channel As Enterprise.Model.Channel.IClientChannel = interaction.EntrepriseInteractionCurrent.ActiveChannel 'agent.Channel
Dim protocol As IProtocol = channel.Protocol
Dim kvp As Platform.Commons.Collections.KeyValueCollection = New Platform.Commons.Collections.KeyValueCollection()
kvp.Add("keyname", "keyvalue")
Dim userevent As Platform.Voice.Protocols.TServer.CommonProperties = Platform.Voice.Protocols.TServer.CommonProperties.Create()
userevent.UserData = kvp
Dim connID As Platform.Voice.Protocols.ConnectionId = Nothing
Dim interactionVoice as IInteractionVoice = TryCast(interaction, IInteractionVoice)
If interactionVoice IsNot Nothing Then
userevent.UserEvent = Platform.Voice.Protocols.TServer.Events.EventUserEvent.MessageId
connID = New Platform.Voice.Protocols.ConnectionId(interactionVoice.TConnectionId)
Dim strDN As String = Nothing
'ensure the correct DN is passed when attaching reason codes, in case agent is logged into multiple DNs
Dim devices() As Enterprise.Model.Device.IDevice = interactionVoice.Device
Dim device As Enterprise.Core.DN = devices(0)
strDN = device.Name
userevent.ThisDN = strDN
userevent.ConnID = connID
Dim req = Platform.Voice.Protocols.TServer.Requests.Special.RequestSendEvent.Create()
req.UserEvent = userevent
'send request
protocol.Send(req)
End If
End If
End Function

InitiateShutdown fails with RPC_S_SERVER_UNAVAILABLE error for a remote computer

I'm trying to implement rebooting of a remote computer with InitiateShutdown API using the following code, but it fails with RPC_S_SERVER_UNAVAILABLE or 1722 error code:
//Process is running as administrator
//Select a remote machine to reboot:
//INFO: Tried it with and w/o two opening slashes.
LPCTSTR pServerName = L"192.168.42.105";
//Or use 127.0.0.1 if you don't have access to another machine on your network.
//This will attempt to reboot your local machine.
//In that case make sure to call shutdown /a /m \\127.0.0.1 to cancel it.
if(AdjustPrivilege(NULL, L"SeShutdownPrivilege", TRUE) &&
AdjustPrivilege(pServerName, L"SeRemoteShutdownPrivilege", TRUE))
{
int nErrorCode = ::InitiateShutdown(pServerName, NULL, 30,
SHUTDOWN_INSTALL_UPDATES | SHUTDOWN_RESTART, 0);
//Receive nErrorCode == 1722, or RPC_S_SERVER_UNAVAILABLE
}
BOOL AdjustPrivilege(LPCTSTR pStrMachine, LPCTSTR pPrivilegeName, BOOL bEnable)
{
HANDLE hToken;
TOKEN_PRIVILEGES tkp;
BOOL bRes = FALSE;
if(!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
return FALSE;
if(LookupPrivilegeValue(pStrMachine, pPrivilegeName, &tkp.Privileges[0].Luid))
{
tkp.PrivilegeCount = 1;
tkp.Privileges[0].Attributes = bEnable ? SE_PRIVILEGE_ENABLED : SE_PRIVILEGE_REMOVED;
bRes = AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0);
int nOSError = GetLastError();
if(bRes)
{
if(nOSError != ERROR_SUCCESS)
bRes = FALSE;
}
}
CloseHandle(hToken);
return bRes;
}
So to prepare for this code to run I do the following on this computer, which is Windows 7 Pro (as I would do for the Microsoft's shutdown tool):
Run the following "as administrator" to allow SMB access to the logged in user D1 on the 192.168.42.105 computer (per this answer):
NET USE \\192.168.42.105\IPC$ 1234 /USER:D1
Run the process with my code above "as administrator".
And then do the following on remote computer, or 192.168.42.105, that has Windows 7 Pro (per answer here with most upvotes):
Control Panel, Network and Sharing Center, Change Advanced Sharing settings
"Private" enable "Turn on File and Printer sharing"
Set the following key:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System
LocalAccountTokenFilterPolicy=dword:1
RUN secpol.msc, then go to Local Security Policy, Security Settings, Local Policies, User Rights Assignment. Add "Everyone" to "Force shutdown from a remote system". (Just remember to remove it after you're done testing!)
Note that the following shutdown command seems to work just fine to reboot the remote computer:
shutdown /r /m \\192.168.42.105 /t 30
What am I missing with my code?
EDIT:
OK. I will admit that I was merely interested in why InitiateShutdown doesn't seem to "want" to work with a remote server connection, while InitiateSystemShutdownEx or InitiateSystemShutdown had no issues at all. (Unfortunately the latter two did not have the dwShutdownFlags parameter, which I needed to pass the SHUTDOWN_INSTALL_UPDATES flag to, which caused my persistence...)
At this point I had no other way of finding out than dusting out a copy of WinDbg... I'm still trying to dig into it, but so far this is what I found...
(A) It turns out that InitiateSystemShutdownEx internally uses a totally different RPC call. W/o too many details, it initiates RPC binding with RpcStringBindingComposeW using the following parameters:
ObjUuid = NULL
ProtSeq = ncacn_np
NetworkAddr = \\192.168.42.105
EndPoint = \\PIPE\\InitShutdown
Options = NULL
or the following binding string:
ncacn_np:\\\\192.168.42.105[\\PIPE\\InitShutdown]
(B) While InitiateShutdown on the other hand uses the following binding parameters:
ObjUuid = 765294ba-60bc-48b8-92e9-89fd77769d91
ProtSeq = ncacn_ip_tcp
NetworkAddr = 192.168.42.105
EndPoint = NULL
Options = NULL
which it later translates into the following binding string:
ncacn_np:\\\\192.168.42.105[\\PIPE\\lsarpc]
that it uses to obtain the RPC handle that it passes to WsdrInitiateShutdown (that seems to have its own specification):
So as you see, the InitiateShutdown call is technically treated as Unknown RPC service (for the UUID {765294ba-60bc-48b8-92e9-89fd77769d91}), which later causes a whole bunch of credential checks between the server and the client:
which, honestly, I'm not sure I want to step into with a low-level debugger :)
At this stage I will say that I am not very well versed on "Local Security Authority" interface (or the \PIPE\lsarpc named pipe configuration.) So if anyone knows what configuration is missing on the server side to allow this RPC call to go through, I would appreciate if you could post your take on it?

OriginalDesiredAccess manipulation in ring0

Simple question. I wrote driver (WDM) which hook itself with callback's and intercept virtual memory functions, terminate, suspend end etc (i want to build little self defense). And.. if i try to terminate my app via standard application (without admin rights) - i can't do that, but if i try same thing via application with debug privileges - program successfully terminating. Where my mistake?
Method do detect WriteMemoryProcess:
if ((OperationInformation->Parameters->CreateHandleInformation.OriginalDesiredAccess & PROCESS_VM_WRITE) == PROCESS_VM_WRITE)
{
OperationInformation->Parameters->CreateHandleInformation.DesiredAccess &= ~PROCESS_VM_WRITE;
}
Callback registration:
RegisterOperation.ObjectType = PsProcessType;
RegisterOperation.Operations = OB_OPERATION_HANDLE_CREATE;
RegisterOperation.PreOperation = ObjectPreCallback;
RegisterOperation.PostOperation = ObjectPostCallback;
RegisterCallBack.Version = OB_FLT_REGISTRATION_VERSION;
RegisterCallBack.OperationRegistrationCount = registrationCount;
RtlInitUnicodeString(&Altitude, L"XXXXXXX");
RegisterCallBack.Altitude = Altitude;
RegisterCallBack.RegistrationContext = &RegistrationContext;
RegisterCallBack.OperationRegistration = &RegisterOperation;
Thanks for advice!

Unable to connect to ftp server

I'm trying to connect to an ftp server through a powerbuilder application using windows api functions. I manage to connect to the ftp server through Internet Explorer (so I don't think it's a permission problem) but the application fails for some unknown reason.
String ls_Null, &
ls_id
Integer li_rc
li_rc = 1
IF Not InternetAutodial(AUTODIAL_FORCE_UNATTENDED, 0) THEN
f_write_to_err_log('IMPORT Unable To Connect Internet - Dialup')
li_rc = -1
ELSE
SetNull(ls_Null)
ls_id = "Care_Dsend"
al_internet_handle = InternetOpen(ls_id, INTERNET_OPEN_TYPE_DIRECT, ls_Null, ls_Null, 0)
IF al_internet_handle > 0 THEN
al_ftp_connect_handle = InternetConnect(al_internet_handle, is_ftp_url, il_ftp_port, is_ftp_user, is_ftp_password, INTERNET_SERVICE_FTP, INTERNET_FLAG_PASSIVE, al_ref)
END IF
END IF
Return li_rc
//al_internet_handle, al_ftp_connect_handle are by ref long parms
//al_ref is a by ref unsignedlong parm
//is_ftp_url, is_ftp_user, is_ftp_password are strings
//il_ftp_port is long
The function manages to return a handle from the InternetOpen api function, but returns 0 from the InternetConnect function.
Any ideas?
Ok, I found out what the problem was. I was missing ;Ansi at the end of my function declaration as in :
Function ulong InternetOpen (ref
string lpszAgent, ulong dwAccessType,
ref string lpszProxy, ref string
lpszProxyBypass, ulong dwFlags)
Library "WININET.DLL" Alias for
"InternetOpenA ;Ansi"
Can you post your Local External Functions or whatever you are using for InternetAutodial(), InternetOpen() etc? Those are not built-in functions (at least not in my Powerbuilder 11.2) and they don't look like PFC. Also, what version of Powerbuilder are you using.
Alternatively, you might want to look at these links:
Upload a file using FTP - Real's Powerbuilder HowTo (also uses a windows batch file)
Internet services example - PFC guide (uses PFC)

Changing RealBASIC permissions on non-admin Mac

My app needs to write (and move) files to a folder from a non-admin user, and that user has no permission to use that folder.
I tried changing the permissions for the folder but it doesn't appear to have an effect.
Are there built-in restrictions from allowing me to do that?
What I do is write to Documents and then attempt to move file to final folder, which fails...
Thanks for any answers!
Here is the code:
Dim t as TextOutputStream
Dim tempfile as FolderItem = SpecialFolder.Documents.Child(filePath.Name)
t = tempfile.CreateTextFile
t.Write fileData
t.close
Dim p as New Permissions( 0 )
p.OthersExecute = True
p.OthersWrite = True
p.OthersRead = True
filePath.Parent.Permissions = p
tempfile.MoveFileTo filePath.Parent
The OS is designed to STOP this sort of thing as it's a huge security hole otherwise
You could use one of the functions in the Monkeybread Software plugin, AuthorizationMBS, to allow authorization, assuming the user can elevate the security level. In a class of mine that has to get into a System location, I have this:
Protected Function mbsAuthorize() As boolean
dim a as AuthorizationMBS
dim s(2) as String
if mbsAuthorized then
mbsForm = mbsAuth.ExternalForm
Return true
else
a = New AuthorizationMBS
If a.NewAuthorization(nil, a.kAuthorizationFlagPreAuthorize) Then
a.SimpleAuthorize
if a.Authorized then
mbsAuth=a // save so the externalform doesn't get invalid
mbsForm=a.ExternalForm // copy to string for later use.
Return true
end if
else
break
End if
end
return false
End Function
The class has these properties:
mbsForm as string
mbsAuth as AuthorizationMBS

Resources