windbg script to enumerate process using actieprocesslink

I need to write a script that list the process using activeprocesslinks in eprocess object.
I started the address I get from PsActiveProcessHead

Below is the script

$$ Get process list LIST_ENTRY in $t0.
r $t0 = nt!PsActiveProcessHead

$$ Iterate over all processes in list using actieprocesslink

.for(r? $t1 = (nt!_EPROCESS*)@$t0; (@$t1 != 0) & (@$t1 != @$t0); r? $t1 = ( (nt!_EPROCESS*)((@$t1->ActiveProcessLinks.Flink+4 )-88 ) )
{

$$ Get image name into $ImageName.
as /ma ${/v:$ImageName} @@C++(@$t1->ImageFileName)

.block
{

.echo ${$ImageName}
}

ad $ImageName

}

I am not getting any error messages but no output also.
Can anybody help me on this.

Thanks,
Abhijit

For starter calculation of $t1 is wrong - you basically assign
nt!PsActiveProcessHead value as nt!_EPROCESS*. This is incorrect for
two reasons. First, nt!PsActiveProcessHead symbol holds pointer to
pointer to first LIST_ENTRY structure so you need to dereference it.
And second, this structure (and ActiveProcessLinks field in
particular) is not the beginning of _EPROCESS structure. So if you
actually want to still follow this route you should have something
like ‘r? $t1 = (nt!_EPROCESS*)(@@masm(poi(@$t0))-#FIELD_OFFSET(nt!_EPROCESS,ActiveProcessLinks))’.

Now, the other problem is that what you have contains hardcoded
offsets and since you didn’t provide what version of OS you’re using
it’s impossible to tell if this is also an issue for you.

I haven’t looked at the rest of your .for statement but most likely it
also has problems with how you’re interpreting content of your
temporary registers. I would rewrite it again using #CONTAINING_RECORD
macro. And btw. there is a sample script of exactly what you need in
windbg help - just search it through for PsActiveProcessHead.

Kris

On Sat, Aug 10, 2013 at 6:35 PM, wrote:
> I need to write a script that list the process using activeprocesslinks in eprocess object.
> I started the address I get from PsActiveProcessHead
>
> Below is the script
> ==========
> $$ Get process list LIST_ENTRY in $t0.
> r $t0 = nt!PsActiveProcessHead
>
>
> $$ Iterate over all processes in list using actieprocesslink
>
> .for(r? $t1 = (nt!_EPROCESS*)@$t0; (@$t1 != 0) & (@$t1 != @$t0); r? $t1 = ( (nt!_EPROCESS*)((@$t1->ActiveProcessLinks.Flink+4 )-88 ) )
> {
>
> $$ Get image name into $ImageName.
> as /ma ${/v:$ImageName} @@C++(@$t1->ImageFileName)
>
> .block
> {
>
> .echo ${$ImageName}
> }
>
> ad $ImageName
>
>
> }
> ==============
> I am not getting any error messages but no output also.
> Can anybody help me on this.
>
> Thanks,
> Abhijit
>
>
> —
> WINDBG is sponsored by OSR
>
> OSR is hiring!! Info at http://www.osr.com/careers
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer


Kris

Hi Kris,

I am working on xp sp2. I came across the code that uses #CONTAINING_RECORD on msdn.
but I would choose to use this method . I ll try to use #FIELD_OFFSET macro.

Abhijit

Here’s an example script that I use for Debug Lab:

$$
$$ listprocs.wbs
$$
$$ Walk the current list of processes
$$
$$ OSR Open Systems Resources, inc.
$$
$$ http://www.osr.com
$$ http://www.osronline.com
$$
$$
$$ To run:
$$
$$ $$><listprocs.wbs>$$

.echo
.echo * This command brought to you by osronline.com
.echo


$$ Global aliases

$$ Note that we use ${/v:} around all of our alias names. This shuts
$$ alias expansion OFF for these names. Without these, multiple invocations
$$ of the script can cause issues

$$ Cast the active process list head as a LIST_ENTRY pointer

aS ${/v:PsActiveProcessHead} "@@c++((nt!_LIST_ENTRY
)@@masm(nt!PsActiveProcessHead))"

$$ This is the offset of the list entry that PsActiveProcessHead points to

aS ${/v:ProcessLinksOffset} “@@c++(#FIELD_OFFSET(nt!_EPROCESS,
ActiveProcessLinks))”

$$ And the offset to the 16 character ANSI name

aS ${/v:ImageNameOffset} “@@c++(#FIELD_OFFSET(nt!_EPROCESS,
ImageFileName))”

$$ Locals

aS ${/v:listEntry} “@$t0”
aS ${/v:currProc} “@$t1”

$$ Force the script to evaluate the above aliases with a .block
.block
{

$$ Get the Flink value of the head. Note that r? is required
$$ to use the C++ syntax in the r statement. Also, the type is
$$ assigned to the resulting register

r? ${listEntry} = @@c++(${PsActiveProcessHead}->Flink)

$$ And loop while we have entries…

.while (${listEntry} != ${PsActiveProcessHead})
{

$$ Get the base of the struct from the list pointer.
$$ Note that #CONTAINING_RECORD would also work

r ${currProc} = ${listEntry} - ${ProcessLinksOffset}

$$ Dump the ASCII 16 character name in the process

da ${currProc} + ${ImageNameOffset}

$$ Move on to the next entry. Our r? command makes sure
$$ that ${listEntry} is typed appropriately

r? ${listEntry} = @@c++(${listEntry}->Flink)

}
}

$$ /v: suppresses the alias expansion

ad ${/v:currProc}
ad ${/v:listEntry}
ad ${/v:ProcessLinksOffset}
ad ${/v:ImageNameOffset}
ad ${/v:PsActiveProcessHead}

-scott
OSR</listprocs.wbs>

Thanks Scott

I could code it. I just used pseudo registers.

Pasting it here if anybody needs it for future refernce

r $t0 = nt!PsActiveProcessHead
.printf “process head= %p\n”,@$t0

r? $t2 = (nt!_EPROCESS*)(@@masm(@$t0) - #FIELD_OFFSET(nt!_EPROCESS,ActiveProcessLinks))
r? $t3= @$t2->ActiveProcessLinks.Flink

$$storing for terminating condition
r? $t5 = @$t3

$$ below starts system process pid 0
r? $t2 = (nt!_EPROCESS*)(@@masm(@$t3) - #FIELD_OFFSET(nt!_EPROCESS,ActiveProcessLinks))
r? $t3= @$t2->ActiveProcessLinks.Flink

.printf “flink= %x\n”,@$t3
r? $t4 = @$t2->ImageFileName
da @$t4

.while(@$t3 != @$t5)
{
.printf “---------\n”

r? $t2 = (nt!_EPROCESS*)(@@masm(@$t3) - #FIELD_OFFSET(nt!_EPROCESS,ActiveProcessLinks))
r? $t3= @$t2->ActiveProcessLinks.Flink

.printf “flink= %x\n”,@$t3
r? $t4 = @$t2->ImageFileName
da @$t4
.printf “===============\n”

}

Thanks,
Abhijit