PDA

View Full Version : Attach Extended


Hero
March 4th, 2009, 02:25
Hi all
This is a really small plugin that I have written for improving attach feature of OllyDbg.
With this plugin,you can attach to process by identifing its PID directly,not only selecting process list. In addition,you can find PID of process by dragging a small cursor on each window(This can be used on some protection which remove process from process list like GameGuard).

Please let me know about Bugs, and your suggestions for more process attaching options.

Regards

arc_
March 4th, 2009, 07:33
A possible extra feature would be anti-anti-attach. There are various ways a protection system can detect and even prevent a debugger attaching to it, and there are also various ways to counter these tricks. You could look into this subject and automate the countermeasures in your plugin, completely transparently (ie the plugin simply kills/circumvents any anti-attach when attaching, without the reverser even having to know there was an anti-attach at all).

nezumi documents some interesting techniques in the Blogs forum. There also exists a plugin called AttachAnyway which kills some anti-attach methods, but not all.

dELTA
March 4th, 2009, 11:16
Hey Hero, can it attach to (not yet ResumeThread'ed) processes created with the CREATE_SUSPENDED flag, unlike normal Olly? That would be really great...

Hero
March 4th, 2009, 15:30
Quote:
[Originally Posted by arc_;79558]nezumi documents some interesting techniques in the Blogs forum. There also exists a plugin called AttachAnyway which kills some anti-attach methods, but not all.

I will try to read it in blog,and add it to this plugin on my free time.

Quote:
[Originally Posted by dELTA;79562]Hey Hero, can it attach to (not yet ResumeThread'ed) processes created with the CREATE_SUSPENDED flag, unlike normal Olly? That would be really great...

hmmmm
I think this will be a good feature too,but is it possible in theory at all?
If process has started in debug mode,in addition of suspended mode,i think we cannot attach it,because as I know we cannot debug a process which is debugged. But perhaps it is possible on a non-debugging suspended creation process.
I should test if I can attach to a suspended process at all,if yes I surely add it.

Regards

dELTA
March 4th, 2009, 15:44
It should absolutely be possible (from a Debug API viewpoint) to attach to a process created with the CREATE_SUSPENDED flag, it's just a bug in Olly that it can't do it I think.

It would indeed be great if you could add it.

I also added it to the CRCETL, please feel free to update its entry as soon as you release an update (and also specify the version number, which I left out because I didn't know it):

http://www.woodmann.com/collaborative/tools/AttachExtended

Hero
March 5th, 2009, 04:47
Quote:
[Originally Posted by dELTA;79568]It should absolutely be possible (from a Debug API viewpoint) to attach to a process created with the CREATE_SUSPENDED flag, it's just a bug in Olly that it can't do it I think.

It would indeed be great if you could add it.

I also added it to the CRCETL, please feel free to update its entry as soon as you release an update (and also specify the version number, which I left out because I didn't know it):

http://www.woodmann.com/collaborative/tools/AttachExtended


Hi dELTA
I checked olly and noticed that it cannot attach to a suspended process because DebugActiveProcess fails.
Further check shows that in DebugActiveProcess fails at DbgUiConnectToDbg in this line:
Code:

.text:7C950691 xor ecx, ecx
.text:7C950693 mov eax, large fs:18h
.text:7C950699 cmp [eax+0F24h], ecx
.text:7C95069F jnz short loc_7C9506D5 <-this jump occurs

As I remembr,FS:18h contains information for thread,isn't it? Anybody knows what is that data in [eax+0f24h] for?

Edit1: I was WRONG, because after testing on another computer,I noticed that problem is not here,don't know why my other PC was failing here,but it seems I was wrong.
Edit2:Found a bug in olly which prevents to attach suspended process. Trying to solve it now(donna if it there is more bug,but this one is sure) :P

Regards

Hero
March 6th, 2009, 02:00
OK,now I need to get some help....

After checking olly,I noticed a problem that cause olly crashs when you attach to a suspended process.
This happens because you CANNOT get list of modules from a suspended process using EnumProcessModules.
I searched internet and noticed that when you create a process as suspended, it has not informed for its module list by csrss yet,so EnumProcessModules will fail.
I tried to read them directly from PEB of process,but I noticed that PPEB_LDR_DATA field of PEB which contains information for modules is NULL for suspended process.
Any idea how I can get module list of a suspended process?
Do you think kernel's EPROCESS structure contains a valid data?
If there is an article how process modules will load in process by csrss,it will be great help too.
You will see same problem when you try to explore a suspended process with ProcessExplorer too for same reason.

Regards

Kayaker
March 6th, 2009, 22:22
Ok, since you're doing funky stuff how about a funky idea? No idea if this will help with the problem, it's just a hack-and-see thought at the moment.

PEB / PEB_LDR_DATA doesn't get fully initialized until ntdll!LdrpInitializeProcess is called.

http://www.openrce.org/forums/posts/594

LdrpInitializeProcess is called as an APC, which from all accounts won't happen until ResumeThread is called.

http://www.woodmann.com/forum/showthread.php?t=11154


There is a function called Nt/ZwAlertResumeThread, which maps to nt!_KeAlertResumeThread.

http://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/NT%20Objects/Thread/NtAlertResumeThread.html

Code:

NtAlertResumeThread(

IN HANDLE ThreadHandle,
OUT PULONG SuspendCount
);


ThreadHandle
Handle to thread object.

SuspendCount
Returns number of suspend request for thread ThreadHandle
before call NtAlertResumeThread.
If this number is 0, thread will continue execution.


Difference between AlertResumeThread and ResumeThread:
the first one sets Thread Object to alerted state
(so before thread will continue execution, all APC will be executed).



The idea here is to execute the outstanding APC which will call LdrpInitializeProcess, without actually resuming the process.

So find the starting thread valid handle of the suspended process, EPROCESS.ThreadListHead might work.

Increase the suspend count (so you don't actually resume the thread if it drops to 0) in KTHREAD.SuspendCount.

Call NtAlertResumeThread and see what happens.

Check that the SuspendCount is reduced back to the original after you call NtAlertResumeThread.
Hopefully when the original ResumeThread is called, the fact that the LdrpInitializeProcess APC has already been run won't matter to the process starting normally. In the meantime, you've had the opportunity to do whatever it is you want to do re the Olly attach.


btw, your [fs:18h + 0F24h] is probably TEB.DbgSsReserved and is part of the DbgUiConnectToDbg function. Do a "dt _TEB" in WinDbg/LiveKd to check the offset for your OS.


Kayaker

Hero
March 6th, 2009, 23:42

It seems idea is great.
I gonna try it and see what happens...

Kayaker
March 7th, 2009, 00:57
Just thinking you could get the thread handle from NtOpenThread and using the value from ETHREAD.Cid.(UniqueThread) as the required parameter for that API.

As you're probably aware, the EPROCESS and ETHREAD offsets vary with the OS version. There are ways to get offset-independant references to certain of these fields, which you'd of course want for a plugin.

You may already be aware of the "classic" rootkit way of finding the offset of EProcess->ImageFileName by calling the following function from DriverEntry:

Code:

/***********************************************************

GetOffsetOfProcessName

Find offset of EProcess->ImageFileName, irrespective of OS version
(Hoglund/Russinovich)

When called from DriverEntry we are in the System context,
so we simply search the current EPROCESS structure
for the process string "system"

***********************************************************/

ULONG GetOffsetOfProcessName()
{

ULONG ul_offset;
PEPROCESS CurrentEProcess;

////////////////////////////////////////////////////

CurrentEProcess = PsGetCurrentProcess();

// EPROCESS considered no larger than a page size.

for(ul_offset = 0; ul_offset < PAGE_SIZE; ul_offset++)

{
if( !strncmp( "System", (PCHAR) CurrentEProcess + ul_offset,
strlen("System"))
{
return ul_offset;
}
}

return 0;

}

/***********************************************************/



I've developed several more based on this idea of finding the absolute offset of selected fields in a known way. Here are 2 examples that might be pertinent here, and are simply run as an IOCTL from your own driver (context of your own process) and the offsets saved for future reference. I've got several others as well.

To increment KTHREAD.SuspendCount (if you find you need to do that), you might be able to call SuspendThread, incrementing the suspend count (to MAXIMUM_SUSPEND_COUNT).


Code:

// Called from IOCTL

////////////////////////////////////////////////////
// Get the absolute offset of various ETHREAD structre
// entries, regardless of OS version
////////////////////////////////////////////////////

offsetETHREAD_Cid = GetOffsetOfCid();
offsetETHREAD_ThreadListEntry = GetOffsetOfThreadListEntry();



Code:

/***********************************************************

GetOffsetOfCid

Obtain offset of EThread->Cid

http://computer.forensikblog.de/

_ETHREAD version 5.0.2195.7045 Microsoft Windows 2000.
+0x1e0 Cid : struct _CLIENT_ID
+0x000 UniqueProcess
+0x004 UniqueThread

_ETHREAD Version 5.1.2600.0 Windows XP.
+0x1ec Cid : struct _CLIENT_ID

_ETHREAD Version 5.2.3790.0 Microsoft Windows Server 2003
+0x1f4 Cid : struct _CLIENT_ID

***********************************************************/

ULONG GetOffsetOfCid()
{

ULONG ul_offset;
ULONG CurrentProcessId;
PETHREAD CurrentEThread;


////////////////////////////////////////////////////

CurrentProcessId = (ULONG)PsGetCurrentProcessId();
CurrentEThread = PsGetCurrentThread();

// ETHREAD considered no larger than a page size.

for(ul_offset = 0; ul_offset < PAGE_SIZE; ul_offset++)
{
if( *(ULONG*) ( (BYTE*)CurrentEThread + ul_offset) == CurrentProcessId )
{
// found _CLIENT_ID.UniqueProcess
return ul_offset;
}
}

return 0;

}

/***********************************************************/


Code:

/***********************************************************

GetOffsetOfThreadListEntry

Obtain offset of EThread->ThreadListEntry

EPROCESS.ThreadListHead is a linked list pointer to
ETHREAD.ThreadListEntry

EPROCESS +0x050 ThreadListHead : struct _LIST_ENTRY
+0x000 Flink
+0x004 Blink

http://computer.forensikblog.de/

_ETHREAD version 5.0.2195.7045 Microsoft Windows 2000.
+0x1a4 ThreadListEntry : struct _LIST_ENTRY

_ETHREAD Version 5.1.2600.0 Windows XP.
+0x1b0 ThreadListEntry : struct _LIST_ENTRY

_ETHREAD Version 5.2.3790.0 Microsoft Windows Server 2003
+0x1ac ThreadListEntry : struct _LIST_ENTRY

***********************************************************/

ULONG GetOffsetOfThreadListEntry()
{

PEPROCESS CurrentEProcess;
PETHREAD CurrentEThread;
ULONG pThreadListEntry;

////////////////////////////////////////////////////

CurrentEProcess = PsGetCurrentProcess();
CurrentEThread = PsGetCurrentThread();

pThreadListEntry = (( (unsigned long)
CurrentEProcess->Pcb.ThreadListHead.Flink
));

// Obtain the relative offset of ETHREAD.ThreadListEntry by
// subtracting it with the *known* ETHREAD structure starting offset

return (ULONG)((BYTE*)pThreadListEntry - (BYTE*)CurrentEThread);

}

/***********************************************************/



btw, there's no need to quote the entire post when replying to a post if it's obvious what you're replying to.

Kayaker

Hero
March 7th, 2009, 01:34
hi Kayaker
Calling SuspendThread on a already suspended thread do something more than increasing suspend count of thread?
Because I thought it will be more easier to call SuspendThread on my suspended process in order to increase suspend count rather than manually change values in EPROCESS and ETHREAD, then call NtAlertResumeThread.
But this way is not working or it seems NtAlertResumeThread will alert APC before resuming thread IF decreased suspend count reachs 0, so if we manually increase suspend count NtAlertResumeThread will not alert APC,because suspend count is more than 0.
Am I wrong somewhere?or there is difference between manually change values in EPROCESS and calling SuspendThread?

Edit:
I suddenly thought a strange idea. Is it possible to force LdrpInitializeProcess for that suspended process?
I mean inject a code in order to use our suspended thread PEB rather than current thread one in here:
Code:
:7C921ABC _LdrpInitializeProcess@20 proc near ; CODE XREF: _LdrpInitialize(x,x,x)+88CE
...
:7C921B36 mov eax, large fs:18h ; TEB
:7C921B3C mov ebx, [eax+30h] ; PEB <-in here

Do you think will it be able to intialize PEB_LDR_DATA correctly for our suspended thread?

Regards

Kayaker
March 7th, 2009, 03:19
I dunno. I thought that NtAlertResumeThread might allow the outstanding APC (which will execute LdrpInitializeProcess) to execute. I'm not even sure if that APC has been created/queued yet at that point. There are some ETHREAD fields you could check that might tell you the APC status. If there is an outstanding one, then it's probably the LdrpInit one.

If NtAlertResumeThread won't trigger the APC to run, perhaps you can force the thread into an alertable state, without actually resuming it, with SleepEx (which, like the Wait functions are supposed to accomplish that):

http://msdn.microsoft.com/en-us/library/aa363772(VS.85).aspx

Again this is all guesswork because I don't know what you can force onto an already suspended thread (especially one which hasn't even begun to execute or been fully initialized).

Hero
March 7th, 2009, 11:48
Hi Kayaker
Rather than using those APIs,I found an undocumented API called NtAlertThread that should send thread in alerted state(or at least I think like that...),so APCs should run now.
But nothing happened again,then I think the APCs are not even created when we create process in suspended mode.
So I though for other ways. What do you think is better:
1-Try to find a way to load modules without resuming process.
2-A funny way but I donna if it works always or not: create another instance of process in debug mode,patch a "int 3" at its OEP, and when you stop at that "int 3",get its module list...
3-find out how TLS works... how TLS routines can call API function? TLS routines run even though you create process as suspended,then how they can call APIs whithout having modules loaded?or I'm wrong and modules are loaded in suspended mode,but PEB_LDR_DATA has not filled yet?

Regards