This example program shows what to do, in order to access for example LPT port. First it checks the current user name. If it is not SYSTEM, a scheduled task is created with the NetScheduleJobAdd api. We need to be run in system account because the ZwSetInformationProcess function that can grant us direct I/O access, requires TCB privilege (act as part of the operating system) which is not available even for administrators.
$include "windowssdk.inc"
$include "lmcons.inc"
$include "mstask.inc"
$include "lmat.inc"
$include "wchar.inc"
$include "stdio.inc"
$include "conio.inc"
$include "ntddk.inc"
$include "undocumented.inc" /* compile for console */
$use "msvcrt.lib" ' for _inp, _outp
' check current user name - if it is SYSTEM, jump to SystemMain(), else
' create, run scheduled task and quit
UserMain()
' this function is called when your program is running in most privileged system account
sub SystemMain()
' %USERNAME% = SYSTEM
print "toggling LPT bits. Press any key to quit"
int IOPL = 3
' show current I/O Privilege Level
PrintCurrentIOPL()
' adjust I/O Privilege Level
ZwSetInformationProcess(NtCurrentProcess(), ProcessUserModeIOPL, &IOPL, len(IOPL))
' show I/O Privilege Level after adjusting
PrintCurrentIOPL()
while (kbhit() = 0)
Beep(900,40)
outp(888, 255)
Sleep(200)
Beep(910,40)
outp(888, 0)
Sleep(200)
endwhile
return
endsub
sub PrintCurrentIOPL(),int
int EFLAGS=0
int iopl
_asm
pushfd
pop dword[ebp-4] ; store EFLAGS register to EFLAGS variable
_endasm
iopl = (EFLAGS>>12) & 3
print "current I/O Privilege Level: ", iopl
return iopl
endsub
sub UserMain()
iwstring text[32]
AT_INFO at
DWORD cch = 32
' query name of current user
GetUserNameW(text, &cch)
if (wcsicmp(text, L"SYSTEM") = 0)
SystemMain()
return
endif
' if not SYSTEM, then switch to SYSTEM using scheduled task
memset(&at, 0, len(at))
at.Command = GetCommandLineW()
DWORD dwJob
CoInitialize(NULL)
NET_API_STATUS status = NetScheduleJobAdd(NULL, &at, &dwJob)
if (status = 2184)
' schedule service has not been started
' this is temporary! You should use StartService()
_system("sc start schedule")
Sleep(1000)
status = NetScheduleJobAdd(NULL, &at, &dwJob)
endif
if (status = 0)
' create job name
wsprintfW(text, L"At%d", dwJob)
ITaskScheduler scheduler
if (CoCreateInstance(_CLSID_CTaskScheduler, NULL, CLSCTX_INPROC_SERVER, _IID_ITaskScheduler, &scheduler) = S_OK)
ITask task=0
if (scheduler->Activate(text, _IID_ITask, &task) = S_OK)
if (task->Run() = S_OK)
' task is queued for run, wait a little
HRESULT hrStatus = SCHED_S_TASK_HAS_NOT_RUN
BOOL fWait = TRUE
while (fWait)
Sleep(200)
ITask task2=0
if (scheduler->Activate(text, _IID_ITask, &task2)) then _
goto break
task2->GetStatus(&hrStatus)
if (hrStatus <> SCHED_S_TASK_HAS_NOT_RUN) then _
fWait = FALSE
task2->Release()
endwhile
break:
endif
task->Release()
endif
' delete the scheduled task
scheduler->_Delete(text)
scheduler->Release()
endif
endif
CoUninitialize()
return
endsub
Sapero
When I try compile this application en run it it give my endless loop !
How can I read and write the Timers in my PC the hardware chip PIT ?
Kind regards
Stephane