Monday, March 19, 2012

[ Issue ] WinDbg - Waiting to reconnect ?

While reverse engineering and possibly in some cases of malware anlysis (Debugging kernel components like rootkits) you need to manage your environment remotely and when there are kernel drivers, it's better to debug them remotely in an isolated environment .
There is a common issue through Windbg users, and indeed it's not a windbg design flaw, it's the speed rate issue .
Ocassionaly windbg users have issue while connecting to remote guess machine for debugging the underlying application and the common problem faced with the statement "Why it is too slow!?".
Now, I have the solution here, although it is not new but it is nice to introduce it here .
VirtualKD aims to make your speed at remote debugging up to ~450 KB/s .


Prepare for installation and Running

  • First of all, Sysprog's VirtualKd located here,download it (make me aware if you're facing any kind of broken link, fix it up soon possibly)
  • Once you downloaded it, upon running it, main package will start to download, let it get working and download the full content .
  • Once main packaged downloaded completely, run "VirtualKDSetup.exe" for configuration
    • VirtualKd made for VMWare and VirtualBox, but in case of using VirtualKd for remote debugging I highly recommend you, using VirtualBox instead of VMware.
  • Upon running "VirtualKd.exe" you will see the following image
  • Before running one step further, download the latest version of Oracle VirtualBox here. (at time of this writing the current version is 4.1.10)
  • Once the installer detect your clean installation of virtualbox, you will see the statement "VirtualBox 4.x.x detected, No problems found." in bottom of Integrate Into VirtualBox button .
  • Now it's time to click integrate into VirtualBox to let the VKD, make it's configurations and integrations well, so be patient to integrate it .
  • Click Automatic Integration
  • Now run-up your virtual machine (The VM you would like to act  it as debuggee) 
  • From the VirtualKd full package folder, change your path to target folder, you see these contents well :
  • Copy/Paste "vminstall.exe" into your virtual-machine .
  • run & install it for making remote debugging feature enable to kernel
  • Let your VM to restart and see the result of your work



  • Once facing this screen, on the main machine (The machine that runs your debugger for debugging) run up "vmmon.exe" on your debugger machine, you will see it can detect your vm well

 
  • Upon selecting the Os you wanted to enter (I Mean on VM "Microsoft Windows XP Professional [VirtualKD] [Debugger Enabled]), the vmmon.exe will warm up your debugger (in this case WinDbg) and make the right connection to it without any mistakes!
Happy remote-bug-hunting! :]





Thursday, March 15, 2012

AnonymousOS

Indeed, it is not the first time that anonymous movement are contributing to security community by their own tools. as you may already know they made some types of DDoS attack tools (LOIC), but this time, they came with their own OS .
As I am already very interested in Any types of OS and their internal structure I decided to introduce their recent linux os known as "AnonymousOS" based on ubuntu 11.10 .
At time of this writing I have no experience with running their OS and test what's going on.
As shown in screenshots, the appearance is well pretty .




The said the main base system is Linux Ubuntu 11.10 and as I have it already it is good in performance (I mean ubuntu 11.10 not AnonOS) .




With respect to anyone who tried to repart this OS, I think it's not a special thing and just have some tweaks .
Anyway, if you like interested on it, grab it here.

Thursday, March 8, 2012

#AntiSec released symantec antivirus 2006 source code [All platforms]

Famous revolution know as "Anonymous" as their part of #AntiSec operation leaked the full source code of high profile antivirus vendor "Symantec" product "Antivirus 2006" today .


Of course it's a tight response to FBI and cyber threat analyst who are in relation with the recent Anonymous members arrest and sabu snitches in coordination with FBI .


Here you can grab symantec source code.

Kernel Thread Creation #PsCreateSystemThread

 Basically a Thread is an OS concept which allows you to run a small piece of execution code into a running process.
It's clear than implementation of threads differs in different operating systems, as already you might know, threads in a single process share their resources like memory and address space, however in processes the concept is totally different, processes have their own set of resources which are not share together .
As already mentioned conceptually threads are inside processes, here's the illustration :





Threads can scheduled by the operating system, in case of multithreading context switching let the processor to switch between different threads on a process .

The kernel of an operating system is responsible for manipulation of objects like threads for creation, monitoring, termination and etc .

Processes and Threads in combination in most operating systems are divided into two set of implementation :
  • User Mode Implementation (User-Land)
  • Kernel Mode Implementation (Kernel-Land)
In case of kernel threads, these threads are the lightest threads, within each process there is at-least one kernel thread, however in situations where a process have different kernel threads, they're sharing resources as mentioned above .
other threads are User-Space threads, operating system don't aware of them and these threads are in control and schuduled by userspace and implementation of these threads are carried out by usermode libraries .

With this basic set of information we are going to implement a kernel thread in windows xp service pack 3.

There's an almost an undocumented function in windows kernel "ntoskrnl.exe" named "PsCreateSystemThread", it's also notable that this function is exported by "ntoskrnl.exe" and "ntkrnlpa.exe" (Physical address enabled version of windows kernel) .

Well, all we need to run out is tracing PsCreateSystemThread and see what's going on this thread .
as you can see in loc_4A23FA parameters are pushed into the stack in reverse order, so we conclude that the first parameter is a ThreadHandle that give us the possibility of manipulating threads, needness to going to MSDN we're trying to inspect legal parameters out :

NTSTATUS __stdcall PsCreateSystemThread
(
                   PHANDLE ThreadHandle,
                   ULONG DesiredAccess, 
                   POBJECT_ATTRIBUTES ObjectAttributes, 
                   HANDLE ProcessHandle, 
                   PCLIENT_ID ClientId,
                   PKSTART_ROUTINE StartRoutine, 
                   PVOID StartContext
);
Reversing the prototypes out give us the parameters, so as a conclusion to that inspection we're now have 7 parameters there :
  • PHANDLE ThreadHandle  -> out parameters which gives a handle to us
  • ULONG Desired Access    -> Requested access type of the thread with ACCESS_MASK
  • POBJECT_ATTRIBUTES ObjectAttributes  -> filled POBJECT_ATRIBUTES data structure
  • HANDLE ProcessHandle  -> Specified the process you want to create to                 
  • PCLIENT_ID ClientId      -> we set this to 0
  • PKSTART_ROUTINE StartRoutine -> our entry in driver
  • PVOID StartContext -> ripped from MSDN (Supplies a single argument that is passed to the thread when it begins execution)
Let's have some fun with windbg & inspect what's going on in "PsCreateSystemThread"






More close on last jne instruction :





Well, if you're be more close, PsCreateSystemThread calls PspCreateThread to accomplish the thread creation task .


What is PsCreateThread is actually is what you is an almost Pseudocode there :


NTSTATUS __stdcall sub_4A12D0(int a1, ACCESS_MASK AccessMask, int a3, HANDLE Handle, 
int a5, int a6, unsigned int a7, int a8, char a9, unsigned int a10, int a11)
{


  int v74; // [sp+E4h] [bp-54h]@39
  int v75; // [sp+E8h] [bp-50h]@5
  int v76; // [sp+ECh] [bp-4Ch]@6
  int v77; // [sp+F0h] [bp-48h]@6
  LARGE_INTEGER CurrentTime; // [sp+F4h] [bp-44h]@23
  int v79; // [sp+FCh] [bp-3Ch]@1
  NTSTATUS v80; // [sp+100h] [bp-38h]@19
  BOOLEAN v81; // [sp+107h] [bp-31h]@25
  KPROCESSOR_MODE PreviousMode[4]; // [sp+108h] [bp-30h]@1
  LONG AccessStatus; // [sp+10Ch] [bp-2Ch]@25
  BOOLEAN MemoryAllocated[4]; // [sp+110h] [bp-28h]@24
  PSECURITY_DESCRIPTOR SecurityDescriptor; // [sp+114h] [bp-24h]@24
  int BugCheckParameter1; // [sp+118h] [bp-20h]@20
  int v87; // [sp+11Ch] [bp-1Ch]@1
  CPPEH_RECORD ms_exc; // [sp+120h] [bp-18h]@21


  v79 = *MK_FP(__FS__, 292);
  JUMPOUT(a10, 0, *(unsigned int *)loc_4A19F0);
  PreviousMode[0] = 0;
  v87 = 0;
  v11 = 0;
  v72 = 0;
  if ( Handle )
  {
    result = ObReferenceObjectByHandle(Handle, 2u, PsProcessType, PreviousMode[0], &Object, 0);
    v11 = Object;
    v72 = Object;
  }
  else
  {
    if ( a10 )
    {
      v11 = (void *)a5;
      ObfReferenceObject(a5);
      v72 = (void *)a5;
      result = 0;
    }
    else
    {
      result = -1073741816;
    }
  }
  if ( result >= 0 )
  {
    JUMPOUT(PreviousMode[0], 0, *(unsigned int *)loc_4A19DF);
    v13 = ObCreateObject(PreviousMode[0], (int)PsThreadType, a3, *(int *)PreviousMode, 0, 600, 0, 0, (int)&v75);
    if ( v13 < 0 )
    {
      v35 = v13;
      ObfDereferenceObject(v11);
      return v35;
    }
    v14 = v75;
    memset((void *)v75, 0, 0x258u);
    *(_DWORD *)(v14 + 564) = 0;
    *(_DWORD *)(v14 + 544) = v11;
    *(_DWORD *)(v14 + 492) = *((_DWORD *)v11 + 33);
    v76 = v14;
    v77 = 0;
    v15 = sub_490D5C(dword_48A4E0, &v76);
    *(_DWORD *)(v14 + 496) = v15;
    if ( v15 )
    {
      *(_DWORD *)(v14 + 576) = dword_47A53C;
      KeInitializeSemaphore((PRKSEMAPHORE)(v14 + 500), 0, 1);
      *(_DWORD *)(v14 + 460) = v14 + 456;
      *(_DWORD *)(v14 + 456) = v14 + 456;
      *(_DWORD *)(v14 + 532) = v14 + 528;
      *(_DWORD *)(v14 + 528) = v14 + 528;
      *(_DWORD *)(v14 + 472) = v14 + 468;
      *(_DWORD *)(v14 + 468) = v14 + 468;
      *(_DWORD *)(v14 + 568) = 0;
      KeInitializeSpinLock((PKSPIN_LOCK)(v14 + 480));
      *(_DWORD *)(v14 + 488) = v14 + 484;
      *(_DWORD *)(v14 + 484) = v14 + 484;
      v61 = (char *)v11 + 128;
      if ( (unsigned __int8)ExAcquireRundownProtection() )
      {
        JUMPOUT(a7, 0, *(unsigned int *)loc_4A19FE);
        v87 = 0;
        _EAX = 16;
        _EDX = v14 + 584;
        __asm { lock or [edx], eax }
        *(_DWORD *)(v14 + 548) = a10;
        v16 = sub_4A169D(v14, 0, sub_4A241F, a10, a11, 0, 0, v11);
        if ( v16 < 0 )
        {
          if ( v87 )
          {
            sub_4A0DB0((ULONG_PTR)v11, v87);
            *(_DWORD *)(v14 + 32) = 0;
          }
        }
        else
        {
          v19 = v79;
          --*(_DWORD *)(v19 + 212);
          v69 = (char *)v11 + 108;
          _ECX = (int)((char *)v11 + 108);
          _EDX = 2;
          __asm { cmpxchg [ecx], edx }
          if ( !(*((_BYTE *)v11 + 584) & 8) )
          {
            v24 = *((_DWORD *)v11 + 104);
            *((_DWORD *)v11 + 104) = v24 + 1;
            v25 = *((_DWORD *)v11 + 101);
            *(_DWORD *)(v14 + 556) = (char *)v11 + 400;
            *(_DWORD *)(v14 + 560) = v25;
            *(_DWORD *)v25 = v14 + 556;
            *((_DWORD *)v11 + 101) = v14 + 556;
            sub_421912(v14);
            v64 = (char *)v11 + 108;
            _ECX = (int)((char *)v11 + 108);
            _EDX = 0;
            __asm { cmpxchg [ecx], edx }
            v22 = v79;
            v27 = *(_DWORD *)(v79 + 212) == -1;
            ++*(_DWORD *)(v22 + 212);
            if ( v27 )
            {
              if ( *(_DWORD *)(v22 + 52) != v22 + 52 )
              {
                *(_BYTE *)(v79 + 73) = 1;
                LOBYTE(_ECX) = 1;
                HalRequestSoftwareInterrupt(_ECX);
              }
            }
            ExReleaseRundownProtection((char *)v11 + 128);
            if ( !v24 )
            {
              LOBYTE(v28) = 1;
              sub_4AA64B(v11, v28);
              if ( dword_48A580 )
              {
                v74 = (int)&unk_48A560;
                v67 = 8;
                do
                {
                  v39 = sub_56F2AA(v74);
                  v40 = v39;
                  if ( v39 )
                  {
                    v41 = (void (__cdecl *)(_DWORD, _DWORD, _DWORD))sub_56F15E(v39);
                    v41(*((_DWORD *)v11 + 83), *((_DWORD *)v11 + 33), 1);
                    sub_56F3DD(v74, v40);
                  }
                  v74 += 4;
                }
                while ( v67-- != 1 );
              }
            }
            v29 = *((_DWORD *)v11 + 77);
            if ( v29 )
            {
              if ( *(_DWORD *)(v29 + 196) )
              {
                _EAX = (int)((char *)v11 + 580);
                if ( !(*((_BYTE *)v11 + 580) & 5) )
                {
                  _ECX = 4;
                  __asm { lock or [eax], ecx }
                  --*(_DWORD *)(v79 + 212);
                  v63 = v29 + 32;
                  ExAcquireResourceSharedLite((PERESOURCE)(v29 + 32), 1u);
                  v44 = *(_DWORD *)(v29 + 196);
                  if ( v44 )
                    IoSetIoCompletion(v44, *(_DWORD *)(v29 + 200), *((_DWORD *)v11 + 33), 0, 6, 0);
                  ExReleaseResourceLite(v63);
                  v45 = v79;
                  v46 = *(_DWORD *)(v79 + 212) == -1;
                  ++*(_DWORD *)(v45 + 212);
                  if ( v46 )
                  {
                    if ( *(_DWORD *)(v45 + 52) != v45 + 52 )
                    {
                      *(_BYTE *)(v45 + 73) = 1;
                      LOBYTE(v45) = 1;
                      HalRequestSoftwareInterrupt(v45);
                    }
                  }
                }
              }
            }
            sub_494D9E(v14, a8, 1);
            if ( dword_48A540 )
            {
              v73 = (int)&unk_48A520;
              v65 = 8;
              do
              {
                v47 = sub_56F2AA(v73);
                v68 = v47;
                if ( v47 )
                {
                  v48 = (void (__cdecl *)(_DWORD, _DWORD, _DWORD))sub_56F15E(v47);
                  v48(*(_DWORD *)(v14 + 492), *(_DWORD *)(v14 + 496), 1);
                  sub_56F3DD(v73, v68);
                }
                v73 += 4;
              }
              while ( v65-- != 1 );
            }
            sub_40C5C2(v14, 2);
            if ( !a7 )
              goto LABEL_16;
            P = ExAllocatePoolWithTag(0, 0x30u, 0x61437350u);
            if ( P )
            {
              KeInitializeApc(P, v14, 0, sub_49528E, 0, dword_5B8958, 1, 0);
              if ( (unsigned __int8)KeInsertQueueApc(P, dword_5B8954, 0, 0) )
              {
LABEL_16:
                if ( a9 )
                {
                  ms_exc.disabled = 1;
                  sub_421DD9(v14);
                  ms_exc.disabled = -1;
                  if ( *(_BYTE *)(v14 + 584) & 1 )
                    sub_4215D2(v14);
                }
                if ( a7 )
                  v30 = *(_DWORD *)(v79 + 68);
                else
                  v30 = (int)v11;
                v80 = sub_48D1B7(
                        0,
                        v30,
                        (int)&v59,
                        (int)&v60,
                        AccessMask,
                        (PGENERIC_MAPPING)((char *)PsThreadType + 104));
                if ( v80 >= 0 )
                {
                  v80 = ObInsertObject(v14, (int)&v59, AccessMask, 0, 0, (int)&BugCheckParameter1);
                  SeDeleteAccessState(&v59);
                  if ( v80 < 0 )
                  {
                    _EAX = 2;
                    _ECX = v14 + 584;
                    __asm { lock or [ecx], eax }
                    if ( a9 )
                      sub_421D81(v14);
                  }
                  else
                  {
                    ms_exc.disabled = 2;
                    *(_DWORD *)a1 = BugCheckParameter1;
                    if ( a6 )
                    {
                      *(_DWORD *)a6 = *(_DWORD *)(v14 + 492);
                      *(_DWORD *)(a6 + 4) = *(_DWORD *)(v14 + 496);
                    }
                    ms_exc.disabled = -1;
                  }
                  KeQuerySystemTime(&CurrentTime);
                  v32 = (unsigned __int64)(8i64 * *(_QWORD *)&CurrentTime) >> 32;
                  *(_DWORD *)(v14 + 448) = 8 * CurrentTime.LowPart;
                  *(_DWORD *)(v14 + 452) = v32;
                  _EDI = v14 + 584;
                  if ( *(_BYTE *)(v14 + 584) & 2 )
                  {
                    *(_DWORD *)(v14 + 580) = 2032639;
                  }
                  else
                  {
                    v80 = ObGetObjectSecurity((PVOID)v14, &SecurityDescriptor, MemoryAllocated);
                    if ( v80 < 0 )
                    {
                      _EAX = 2;
                      __asm { lock or [edi], eax }
                      if ( a9 )
                        sub_421D81(v14);
                      sub_4219A2(v14);
                      ObfDereferenceObject(v14);
                      ObCloseHandle(BugCheckParameter1, *(int *)PreviousMode);
                      return v80;
                    }
                    SubjectSecurityContext.ProcessAuditId = v11;
                    SubjectSecurityContext.PrimaryToken = (PACCESS_TOKEN)PsReferencePrimaryToken(v11);
                    SubjectSecurityContext.ClientToken = 0;
                    v33 = v14 + 580;
                    v81 = SeAccessCheck(
                            SecurityDescriptor,
                            &SubjectSecurityContext,
                            0,
                            0x2000000u,
                            0,
                            0,
                            (PGENERIC_MAPPING)((char *)PsThreadType + 104),
                            PreviousMode[0],
                            (PACCESS_MASK)(v14 + 580),
                            &AccessStatus);
                    sub_494D55((char *)v11 + 200, SubjectSecurityContext.PrimaryToken);
                    ObReleaseObjectSecurity(SecurityDescriptor, MemoryAllocated[0]);
                    if ( !v81 )
                      *(_DWORD *)v33 = 0;
                    *(_DWORD *)v33 |= 0x61u;
                  }
                  sub_4219A2(v14);
                  ObfDereferenceObject(v14);
                  return v80;
                }
                _EAX = 2;
                _ECX = v14 + 584;
                __asm { lock or [ecx], eax }
                if ( a9 )
                  sub_421D81(v14);
                v16 = v80;
                goto LABEL_77;
              }
              _EAX = 2;
              _ECX = v14 + 584;
              __asm { lock or [ecx], eax }
              ExFreePoolWithTag(P, 0);
            }
            else
            {
              _EAX = 2;
              _ECX = v14 + 584;
              __asm { lock or [ecx], eax }
            }
            v16 = -1073741670;
LABEL_77:
            sub_4219A2(v14);
            sub_4268A9(v14, 2);
            goto LABEL_78;
          }
          v66 = (char *)v11 + 108;
          _ECX = (int)((char *)v11 + 108);
          _EDX = 0;
          __asm { cmpxchg [ecx], edx }
          v38 = *(_DWORD *)(v19 + 212)++ == -1;
          if ( v38 )
          {
            if ( *(_DWORD *)(v19 + 52) != v19 + 52 )
            {
              *(_BYTE *)(v19 + 73) = 1;
              LOBYTE(_ECX) = 1;
              HalRequestSoftwareInterrupt(_ECX);
            }
          }
          sub_54BBBB(v14);
          if ( v87 )
            sub_4A0DB0((ULONG_PTR)v11, v87);
          v16 = -1073741558;
        }
        ExReleaseRundownProtection((char *)v11 + 128);
      }
      else
      {
        v16 = -1073741558;
      }
    }
    else
    {
      v16 = -1073741670;
    }
    ObfDereferenceObject(v14);
LABEL_78:
    result = v16;
  }
  return result;
}

Now, we're going to create our real kernel thread in a windows device driver .
For creating kernel-mode components in windows kernel knows as kernel modules or virtual device drivers, you know it comes to Windows Driver Kit.


Based on realization we grabbed from the above steps, the final code looks like here :

#include<ntddk.h>
NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
);


VOID StartRoutine(IN PVOID StartContext);




#ifdef ALLOC_PRAGMA
#pragma alloc_text( INIT, DriverEntry )
#pragma alloc_text( PAGE, StartRoutine )
#endif






NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
{
PDEVICE_OBJECT  deviceObject=NULL;
NTSTATUS status ;
PVOID tmpObj;
HANDLE ThreadHandle=0;
OBJECT_ATTRIBUTES threadOb;
UNICODE_STRING usDriverName;
/*
threadOb.Length = 24;
    threadOb.RootDirectory = 0;
    threadOb.ObjectName = 0;
    threadOb.Attributes = 512;
    threadOb.SecurityDescriptor = 0;
    threadOb.SecurityQualityOfService = 0;
*/

InitializeObjectAttributes(&threadOb, NULL, 
            OBJ_KERNEL_HANDLE, NULL, NULL);
PsCreateSystemThread(&ThreadHandle,
(ACCESS_MASK) 0L,
&threadOb,
0,
0,
StartRoutine,
0
);

RtlInitUnicodeString(&usDriverName, L"\\Device\\tr1");
status = IoCreateDevice(DriverObject, 0,
                              &usDriverName, 
                              FILE_DEVICE_UNKNOWN,
                              FILE_DEVICE_SECURE_OPEN, 
                              FALSE, &deviceObject);
status = ObReferenceObjectByHandle(ThreadHandle, THREAD_ALL_ACCESS, NULL,
                                         KernelMode, &tmpObj, NULL);
ZwClose(DriverObject);  
   
return status;
 
}


VOID StartRoutine(IN PVOID StartContext)
{
LARGE_INTEGER li;
li.QuadPart=1000000;
while(1){
KeDelayExecutionThread(KernelMode , 0, &li);
DbgPrint("Thread 0.1 is running on your system now!");
}
}



and here's the evidence showing our thread is executing on the context of System process.
Hope it would be helpful .