Windows: Dispatching and Scheduling (a short explanation)

Last week a student asked about the correct difference between Dispatching and Scheduling on Windows systems. Of course, this a long topic to talk and write, mainly when the time is very tight, but I will try to summarize the topic below.

Fundamentally, Dispatching is the the process (or action) of switching from a thread executing to another one, while Scheduling is the action of determining the next thread to be executed on the processor. Additionally, there are typical and main states for a thread such as Wait (blocked, waiting any related event occurs), Running (thread is active and running on CPU) and Ready (thread is eligible to run, but it needs to receive an authorization from OS for doing it). A thread can be in Waiting status because a system call (such as an execution of KeWaitSingleObject() by a device driver) and its state is controlled by KTHREAD structure (which is embedded inside the ETHREAD structure and holds information about thread stack, system calls, scheduling, priorities, and so on). A thread can be also in Running status that is determined by KPCR (Kernel Processor Control Region) structure (it can be accessed by functions such as KsGetCurrentThread() and PsGetCurrentProcess()) that holds information about the CPU (if the system has many CPUs, so there’re many KPCRs and each one holds CPU information that is shared by HAL and kernel). During a dispatching, the kernel saves the entire context from the current thread then it executes either the KiSwapThread() or KiSwitchToThread() for loading the context from the new thread.

How does the kernel choose the next thread to be activated and run? It uses the Scheduling feature to pick the next thread to run based on its priority given by Priority field (it can be changed by KeSetPriorityThread(), for example) from KPROCESS structure and respects the BasePriority attribute (the value can changed by using the KeSetBasePriorityThread()) that is the minimum value of Priority attribute. About priorities, there are two valid ranges such as “Dynamic Priority” (from 1 to 15) and “Real Time” (from 16 to 31), where the OS varies the thread’s priority of the former range, but it doesn’t vary the thread’s priority from the latter one. Therefore, real time thread can cause CPU starvation.

The Dynamic Priority value can be changed by operating system when events such as quantum exhaustion (the thread used its time slice), not running (not running threads gain a priority boots for having a chance to run), I/O completion (a driver has finished its I/O job and the current related thread needs of a chance to return to CPU) and KeSetEvent function that helps by bursting the the current thread’s priority to run on CPU.

Changing to a practical approach, examine the colors of the following WinDbg’s output:

lkd> !thread

THREAD fffff80002e58cc0 Cid 0000.0000 Teb: 0000000000000000 Win32Thread: 0000000000000000 RUNNING on processor 0

Not impersonating

DeviceMap fffff8a000008aa0

Owning Process fffff80002e59180 Image: Idle

Attached Process fffffa800a2e6b10 Image: System

Wait Start TickCount 430911 Ticks: 9 (0:00:00:00.140)

Context Switch Count 8568683

UserTime 00:00:00.000

KernelTime 01:45:09.008

Win32 Start Address nt!KiIdleLoop (0xfffff80002cc3570)

Stack Init fffff8000410adb0 Current fffff8000410ad40

Base fffff8000410b000 Limit fffff80004105000 Call 0

Priority 16 BasePriority 0 UnusualBoost 0 ForegroundBoost 0 IoPriority 0 PagePriority 0

Unable to get context for thread running on processor 0, HRESULT 0x80004001

lkd> !pcr

KPCR for Processor 0 at fffff80002e4ad00:

Major 1 Minor 1

    NtTib.ExceptionList: fffff80004103000

     NtTib.StackBase: fffff80004104080

     NtTib.StackLimit: 000000000020e448

     NtTib.SubSystemTib: fffff80002e4ad00

     NtTib.Version: 0000000002e4ae80

     NtTib.UserPointer: fffff80002e4b4f0

     NtTib.SelfTib: 000007fffff82000

     SelfPcr: 0000000000000000

     Prcb: fffff80002e4ae80

     Irql: 0000000000000000

     IRR: 0000000000000000

     IDR: 0000000000000000

     InterruptMode: 0000000000000000

     IDT: 0000000000000000

     GDT: 0000000000000000

     TSS: 0000000000000000

     CurrentThread: fffff80002e58cc0

     NextThread: 0000000000000000

     IdleThread: fffff80002e58cc0

     DpcQueue:

lkd> !ready

Processor 0: No threads in READY state

Processor 1: No threads in READY state

Processor 2: No threads in READY state

Processor 3: No threads in READY state

Processor 4: No threads in READY state

Processor 5: No threads in READY state

Processor 6: No threads in READY state

Processor 7: No threads in READY state

My system is completely idle, but you are able to realize the Current Thread, NextThread (none) and the IdleThread values from the output above. Unfortunately, the WinDbg shows the partial contents of the PCR by using !pcr command.

I know that’s a basic explanation (without digging into excessive details) , but it can helps when you are studying and leaning the internal structures of Windows.

Have a nice day.

Alexandre Borges

(LinkedIn: www.linkedin.com/in/aleborges)

Black Hat USA 2015

Hello readers, how are you? I’m attending the Black Hat USA 2015 from AUG/01 to AUG/06. If you are also attending the event, so send me a message. Honestly, I hope to see you there.

Have a nice day,

Alexandre Borges

(LinkedIn: http://www.linkedin.com/in/aleborges)

MindTheSec Forum Brazil

Dear readers, how are you? The MindTheSec Forum Brazil takes place on AUG/26 and 27 (Sao Paulo), and I will be speaking about Malwares. Certainly, there will be also very important IT Security professionals, so I hope to see you there. :)

MindTheSec: http://mindthesec.com.br and on Twitter: @MindTheSec

Have a nice week.

Alexandre Borges

(LinkedIn: http://www.linkedin.com/in/aleborges)

Gathering SMTP information using Python

Hello readers, how are you? I’ve been working on a penetration test job for a private client and I had to check if specific mail accounts existed on several hosts in the same network. Thus, I lost an hour writing a Python script using multithreading that solved my problem. Honestly, I don’t know if it is interesting for you, but you can adapt for other cases. The script requires some inputs such as a filename containing the users to be tested (root, admin, alex, and so on), the network address (ex. 192.168.1), the beginning and ending range of hosts. It follows the script and an output below:

#!/usr/bin/python

# Written by Alexandre Borges (http://alexandreborges.org)

import sys

import socket

import time

from threading import Thread

# SMTP verification function

def Vrf(ip,f):

try:

    # Create a socket

    socket.setdefaulttimeout(2)

    sock=socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    # Connect to target server

    conn=sock.connect((ip,25))

    # Receive the response

    response=sock.recv(1024)

    # Print the response

    print ‘\t’+response

    # Send the verification command to SMTP server, wait for the answer and print the result

    for user in f.readlines():

sock.send(‘VRFY ‘ + user.strip(‘\n’) + ‘\r\n’)

final=sock.recv(1024)

print ‘\t’+final

sock.close()

    except:

        return

def main():

    # Check the correct syntax

    if len(sys.argv) != 5:

        print “The correct usage is smtpcheck.py <filename> <net_address> <begin_range> <end_range>”

        print “The network address must be entered as X.Y.Z – for example: 192.168.1″

        sys.exit(0)

    # Open the provided file

    arg = sys.argv[1]

    beg = int(sys.argv[3])

    end = int(sys.argv[4])

    net = sys.argv[2]

    filename = open(arg,’r’)

    # Test each system on the range

    for i in range(beg,end):

addr = net + ‘.’ + str(i)

print addr

t = Thread(target=Vrf, args=(addr,filename))

t.start()

time.sleep(0.5)

if __name__==’__main__':

    main()

Output

root@hacker:~# ./smtpcheck.py smtp_list.txt 192.168.1 105 110

192.168.1.105

192.168.1.106

192.168.1.107

    220 metasploitable.localdomain ESMTP Postfix (Ubuntu)

    550 5.1.1 <ale>: Recipient address rejected: User unknown in local recipient table

    550 5.1.1 <fernanda>: Recipient address rejected: User unknown in local recipient table

    550 5.1.1 <test>: Recipient address rejected: User unknown in local recipient table

    252 2.0.0 msfadmin

    252 2.0.0 root

    550 5.1.1 <admin>: Recipient address rejected: User unknown in local recipient table

192.168.1.108

192.168.1.109

 

Please, let me know if you enjoyed it.

Have a nice day.

Alexandre Borges

(Linkedin: http://www.linkedin.com/in/aleborges)

GPU Malware – Update 3

Hello readers, how are you? This is the third update about Malwares that run on GPU (Graphics Processing Units) and keep stealthy. This time I have added a new link (an amazing suggestion from Igor Korkin) below:

Stay tuned for further updates!

If you liked this post then let me know, please.

Have a nice day.

Alexandre Borges

(LinkedIn: http://www.linkedin.com/in/aleborges)

GPU Malware – Update 2

Hello readers, how are you? This is an updated post about Malwares, which run on GPU (Graphics Processing Units) and keep stealthy. I have added two new documents below:

Stay tuned for further updates!

If you liked this post then let me know, please.

Have a nice day.

Alexandre Borges

(LinkedIn: http://www.linkedin.com/in/aleborges)