April 29, 2024, 06:25:54 AM

News:

Own IWBasic 2.x ? -----> Get your free upgrade to 3.x now.........


Impersonation example

Started by sapero, August 27, 2009, 12:54:57 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

sapero

August 27, 2009, 12:54:57 PM Last Edit: September 06, 2009, 02:41:42 PM by sapero
Quote from: MSDNImpersonation is the ability of a thread to execute in a security context that is different from the context of the process that owns the thread.
In this example I'll show how you can impersonate as SYSTEM user to gain whatever you wish - talk to hardware, logon users, easier customize mouse settings for the logon screen, and much more.
If you write security applications and plugins, you could for example write a plugin for Regedit to grant full access to ALL registry keys.

The code was tested on XP.$include "Aclapi.inc"
$include "Sddl.inc"

' for hardware access
$include "conio.inc"   ' inp() outp()
$include "ntddk.inc"
$include "undocumented.inc"
$use "msvcrt.lib"      ' inp() outp()
' additional required import libraries: ntdll.lib /*ntddk.lib was incorrect*/

class CSystemImpersonation
declare CSystemImpersonation()
declare _CSystemImpersonation()

declare Impersonate(),BOOL
declare Revert()
private:
declare InitToken()
declare ModifyTokenAccess(HANDLE hProcess),BOOL
HANDLE m_hToken
BOOL   m_impersonated
endclass


' =========={ example }==========
CSystemImpersonation os

if (os.Impersonate())
' the code here is executed in system (user) context
' when finished, call Revert.

' 1. demo: user name is SYSTEM
string username
int cch = 256
GetUserName(username, &cch)
MessageBox 0, "user name: " + username, ""

' 2. access the hardware (read)
int IOPL = 3
NTSTATUS status = ZwSetInformationProcess(NtCurrentProcess(), ProcessUserModeIOPL, &IOPL, len(IOPL))

' check if the iopl was assigned. ZwSetInformationProcess may return NT_SUCCESS without changing iopl (in virtual pc)
_asm
pushfd      ; push EFLAGS on the stack
pop eax     ; load eflags from stack to eax register
shr eax,12  ; extract iopl  bits
and eax,3
mov [IOPL],eax ; and save in ebasic variable
_endasm

if (IOPL=3)
' iopl was changed for current process (for all threads)
' read byte from the hardware
MessageBox 0, using("value read form port 888 is #", inp(888)), ""
else
' lookup the error code in ntstatus.inc, or call FormatMessage
MessageBox 0, "failed to set IOPL to user mode, error 0x"+hex$(status), ""
endif

' 3. demo - registry
'    a) HKEY_LOCAL_MACHINE - you have full access
'    b) HKEY_CURRENT_USER  - remember, you are running (impersonated) as another user (system)

' leave the SYSTEM impersonation. Only the IOPL will be keept
os.Revert()
else
MessageBox 0, "Impersonate() failed", ""
endif




'==============================

sub CSystemImpersonation::CSystemImpersonation()
m_hToken = 0
m_impersonated = FALSE
endsub


sub CSystemImpersonation::_CSystemImpersonation()
if (m_hToken)
Revert()
CloseHandle(m_hToken)
endif
endsub


sub CSystemImpersonation::InitToken()
HANDLE hProcess = OpenProcess(MAXIMUM_ALLOWED, FALSE, 4)
if (hProcess)
if (ModifyTokenAccess(hProcess))
OpenProcessToken(hProcess, MAXIMUM_ALLOWED, &m_hToken)
endif
CloseHandle(hProcess)
endif
endsub


sub CSystemImpersonation::Impersonate(),BOOL
if (!m_impersonated)
if (!m_hToken) then InitToken()
if (m_hToken) then m_impersonated = ImpersonateLoggedOnUser(m_hToken)
endif
return m_impersonated
endsub


sub CSystemImpersonation::Revert()
if (m_impersonated)
RevertToSelf()
m_impersonated = FALSE
endif
endsub


sub CSystemImpersonation::ModifyTokenAccess(HANDLE hProcess),BOOL

pointer pAcl
pointer pAclMod
EXPLICIT_ACCESS ea
HANDLE hToken

BOOL success = FALSE

if (OpenProcessToken(hProcess, READ_CONTROL | WRITE_DAC, &hToken))

if (!GetSecurityInfo(hToken, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION, 0, 0, &pAcl, 0, 0))

ZeroMemory(&ea, len(ea))
ea.grfAccessPermissions = TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY
ea.grfAccessMode        = GRANT_ACCESS
ea.Trustee.TrusteeForm  = TRUSTEE_IS_SID

if (ConvertStringSidToSid("S-1-1-0", &ea.Trustee.ptstrName))

if (!SetEntriesInAcl(1, &ea, pAcl, &pAclMod))
success = !SetSecurityInfo(hToken, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION, 0, 0, pAclMod, 0)
endif
LocalFree(ea.Trustee.ptstrName)
endif
endif
CloseHandle(hToken)
endif
return success
endsub

Ficko

Hi Sapero! :)

Thanks for the code this is exactlly I am working on and tearing my hair out on the MASM forum.

I wanna find a solution for 64-bit systems but I am running into stuffs.

I checked your prg. it returns zero in "hProcess"

CSystemImpersonation::InitToken()
HANDLE hProcess = OpenProcess(MAXIMUM_ALLOWED, FALSE, 4)

OS: Vista 64

Any suggestion?

Ficko

An update.

I am trying to follow this article:

http://support.microsoft.com/kb/185215/en-us

But I am still getting "ERROR_ACCESS_DENIED" on
OpenProcess(MAXIMUM_ALLOWED, FALSE, 4).

What is "4" stands for ?
Maybe that what Vista don't like?!? >:(

ZeroDog

the "4" is supposed to represent winlogonPid

Ficko

Thanks ZeroDog! :D

I tryed this:


$INCLUDE "WINDOWSSDK.inc"
$INCLUDE "TlHelp32.inc"
OPENCONSOLE
PRINT FindWinLogOn()
WAITCON
END

SUB FindWinLogOn(),INT
PROCESSENTRY32 procEntry
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
IF (hSnap = INVALID_HANDLE_VALUE) THEN RETURN 1
procEntry.dwSize = LEN(PROCESSENTRY32)
IF (!Process32First(hSnap, &procEntry)) THEN RETURN 1
    WHILE (Process32Next(hSnap, &procEntry))
        IF (procEntry.szExeFile = "winlogon.exe") THEN
RETURN procEntry.th32ProcessID
ENDIF
     ENDWHILE
RETURN 0
ENDSUB


it returns "772" but I may messed up the code.

sapero

August 28, 2009, 03:59:32 PM #5 Last Edit: August 28, 2009, 04:01:33 PM by sapero
4 is the id of "SYSTEM" process, on XP (that is, process name is system). See in your task manager - the first entry in process list sorted by PID.

ZeroDog

ah, I see.  I was just basing my guess on examples that other people were working on in other languages.  In every case, it was pointing to the WinLogonPid.  So basically, the variable that "4" is being used in, is simply a process ID.  So perhaps you need to find the process ID for the SYSTEM in vista, and see if that works for the code.

sapero

August 29, 2009, 03:50:55 AM #7 Last Edit: August 29, 2009, 03:52:49 AM by sapero
Quote from: FickoBut I am still getting "ERROR_ACCESS_DENIED"
On Vista you'll need to run your program as administrator, or setup a manifest:<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity processorArchitecture="*" version="5.1.0.0" type="win32" name="Microsoft.Windows.Shell.shell32"/>
<description>Windows Shell</description>
<!-- visual styles -->
<dependency>
<dependentAssembly>
<assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" publicKeyToken="6595b64144ccf1df" language="*" processorArchitecture="*"/>
</dependentAssembly>
</dependency>
<!-- full admin privileges -->
<ms_asmv2:trustInfo xmlns:ms_asmv2="urn:schemas-microsoft-com:asm.v2">
<ms_asmv2:security>
<ms_asmv2:requestedPrivileges>
<ms_asmv2:requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
</ms_asmv2:requestedPrivileges>
</ms_asmv2:security>
</ms_asmv2:trustInfo>
</assembly>

Windows.shell because it was copied form \windows directory :)
Save it as yourprogram.exe.manifest. The same manifest is used in the sdk headers installer.

Ficko

August 29, 2009, 05:56:07 AM #8 Last Edit: August 29, 2009, 06:03:11 AM by Ficko
Thanks Sapero! ;D

Some good news.

The impersonation works on Windows 2000 as well allerdings the process ID is 8.

The sub I posted above works if "winlogon.exe" is changed to "System"

The

pushfd      ; push EFLAGS on the stack
pop eax     ; load eflags from stack to eax register
shr eax,12  ; extract iopl  bits
and eax,3
mov [IOPL],eax ; and save in ebasic variable

not sufficient on virtual machine the "EFLAGS" are "0x80297" despite that "ZwSetInformationProcess" succeed and IOPL is set to 3 properly.
- Tested on host:Vista-64 guest:windows 2000 -

I tryed the manifest file, Administrator, AdjustTokenPrivileges to SeDebugPrivilege no luck still "ERROR_ACCESS_DENIED" on openprocess on VISTA. >:(

Have anybody got this work on vista prehabs on 64-bit at least the first part with the OpenProcess ??




sapero

Have you tried to enable debug privilege - SeDebugPrivilege - before calling OpenProcess?
If the System process will be still denied, choose another process from zero-session - CsrGetProcessId function from ntdll returns process id of csrss.exe for current user, so try to open it instead the "4" pid.

Ficko

August 29, 2009, 08:26:20 AM #10 Last Edit: August 29, 2009, 08:30:18 AM by Ficko
Sapero you are genius! ;D

"CsrGetProcessId" works! :D

Allerdings only with "SeDebugPrivilege" enabled before calling OpenProcess.

"ZwSetInformationProcess" returns "STATUS_NOT_IMPLEMENTED" even with "SeTcbPrivilege" enabled this let's me draw the conclusion that MS stripped this implementation for Vista and above. >:(

Now I have to write a 64-bit driver and figure out how to go by the driversignature nightmare.  ???

Sometimes I like to shake the hands of this MS F*..ers. >:(


Ficko

August 29, 2009, 11:49:19 AM #11 Last Edit: August 29, 2009, 11:52:11 AM by Ficko
I just want to add - before somebody thinks that there is a really solution for vista -  ;)
that the only thing what working is "OpenProcess" but the next call


OpenProcessToken(hProcess, READ_CONTROL | WRITE_DAC, &hToken)


will fail so I do not have a solution for Impersonation for vista jet don't ask me for it. :D

And by finding this discussion I think there never will be one. :(

http://social.msdn.microsoft.com/Forums/en-US/windowssecurity/thread/86602194-c8f7-4c42-b349-fd78e1bdb5f2