Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
259 lines (226 sloc) 10.4 KB
$$
$$ Author: Javier Vicente Vallejo
$$ Twitter: @vallejocc
$$ Web: http://www.vallejo.cc
$$
$$ $$>a<find_injected_pe_rwemem.wdbg
$$
$$ This windbg script will walk the results of !address command for each process in the debuggee machine,
$$ searching for RWE memory containing PE files (based on the analysis of PE header).
$$
$$.sympath SRV*c:\symcache*http://msdl.microsoft.com/download/symbols
$$.reload
aS stage @$t19
aS temp @$t18
aS temp2 @$t17
aS temp3 @$t16
aS isPossiblePE @$t15
aS isDosMessageBased @$t14
aS prev1 @$t7
aS prev2 @$t6
aS baseaddr @$t5
aS baseaddrlen @$t4
.block
{
.sympath "SRV*c:\symcache*http://msdl.microsoft.com/download/symbols";
.reload
}
.block
{
r stage = 2
.printf "xxxx"
.foreach (processes_tok { !process 0 0 })
{
.printf "${processes_tok}\n"
.if($scmp("${processes_tok}","PROCESS")==0)
{
.if(${stage}==2)
{
$$stage==2 is used to skip the first apparition of PROCESS string in the results of !process 0 0
r stage = 0
}
.else
{
r stage = 1
}
}
.elsif(${stage}==1)
{
.printf /D "<b>Analyzing process ${processes_tok}</b>\n"
r stage = 0
.process /i ${processes_tok}
g
.block
{
.reload /user
}
$$search for memory blocks with ReadWriteExecute protection
$$careful:
$$ when the baseaddress is over 0x10000000 findstr tokens will be:
$$ 93:7640:20010000
$$ 2002c000
$$ 1c000
$$ UserRange
$$ ...
$$ however if the addess is under 0x10000000:
$$ 25:1364:
$$ 60000
$$ 61000
$$ 1000
$$ UserRange
$$ The reason for this its windbg puts spaces before the base address when it hasnt 8 characters to complete 8 characters, but if the address is
$$ ???????? then it doesnt put spaces. We need to have in mind both case, and this is the reason of the stages of the next code
$$
.foreach (tok { .shell -ci "!address" findstr /N /O /R /C:"UserRange.*ExecuteReadWrite" /C:"UserRange.*ReadWriteExecute" })
{
r isPossiblePE = 0
r isDosMessageBased = 0
.printf "${tok}\n"
.if($spat("${tok}","*:*:*")!=0)
{
r stage = 1
}
.elsif(${stage}==1)
{
r prev1 = ${tok}
r stage = 2
}
.elsif(${stage}==2)
{
r prev2 = ${tok}
r stage = 3
}
.elsif(${stage}==3)
{
.if($spat("${tok}","*UserRange*")!=0)
{
r baseaddr = prev1 - prev2
r baseaddrlen = prev2
r stage = 5
}
.else
{
r baseaddr = prev1
r baseaddrlen = ${tok}
r stage = 4
}
}
.elsif(${stage}==4)
{
r stage = 5
}
.elsif(${stage}==5)
{
$$for each block with ReadWriteExecute protection, check MZ / PE
r @$t0 = baseaddr
.if(@$t0!=0)
{
.printf "base %x\n", @$t0
.pagein /p ${processes_tok} @$t0
g
$$!address @$t0
.if($vvalid(@$t0, 2)==1)
{
.printf "valid base address\n"
.printf "pe %x\n", @$t0+@@c++(((nt!_IMAGE_DOS_HEADER * )@$t0)->e_lfanew)
.if($vvalid(@$t0+@@c++(((nt!_IMAGE_DOS_HEADER * )@$t0)->e_lfanew), 2)==1)
{
.printf "valid pe header address\n"
.if(wo(@$t0)==0x5a4d & dwo(@$t0+@@c++(((nt!_IMAGE_DOS_HEADER * )@$t0)->e_lfanew))==0x454E)
{
$$We can find MZ / NE images, we ignore them
}
.elsif(wo(@$t0)==0x5a4d & dwo(@$t0+@@c++(((nt!_IMAGE_DOS_HEADER * )@$t0)->e_lfanew))==0x4550)
{
$$if MZ and PE signatures, valid pe header
.printf "valid pe header\n"
r isPossiblePE = 1
}
.else
{
$$if not MZ or not PE signature, but msdos message is found, its a possible pe header
r temp = 0
.foreach (tok2 { s -a @$t0 L 0x80 "This program cannot " })
{
r temp = 1
}
.if(${temp}==1)
{
.printf "possible pe header\n"
r isPossiblePE = 1
r isDosMessageBased = 1
}
}
}
}
$$if we have found a possible PE in a memory zone with ReadWriteExecute protection, we will check if the base address is in the list of loaded module
.if(${isPossiblePE}==1)
{
.printf "is possible module %x\n", @$t0
r temp = 0
$$search for valid from "is not valid address"
.foreach (tok3 { .shell -ci "!lmi @$t0" findstr /N /O "valid.address" })
{
r temp = ${temp} + 1
}
.printf "%x\n", ${temp}
$$ "is not valid address" was found
.if(${temp} > 3)
{
$$ there are some modules that !lmi command is answering: is not valid address, however they seems to be valid loaded modules (not interesing for us).
$$ However if we consults information about the address with !address we find things as:
$$ Memory Usage: Section [\WINDOWS\System32\blablabla.mui] (it happens usually with .mui files, but not only with them
$$ We will discard results of !address with .dll], .mui] and .exe]
r temp = 0
.foreach (tok4 { .shell -ci "!address @$t0" findstr /N /O /R /I "\.mui\]" })
{
r temp = ${temp} + 1
}
r temp2 = 0
.foreach (tok5 { .shell -ci "!address @$t0" findstr /N /O /R /I "\.dll\]" })
{
r temp2 = ${temp2} + 1
}
r temp3 = 0
.foreach (tok6 { .shell -ci "!address @$t0" findstr /N /O /R /I "\.exe\]" })
{
r temp3 = ${temp3} + 1
}
.printf "search !address .mui %x\n", ${temp}
.printf "search !address .dll %x\n", ${temp2}
.printf "search !address .exe %x\n", ${temp3}
.if(${temp} < 4 and ${temp2} < 4 and ${temp3} < 4)
{
.if(${isDosMessageBased}==0)
{
.printf /D "<b>---------------------------------------------------------------------------</b>\n"
.printf /D "<b>Process: ${processes_tok} base: %x -> Possible injected or unpacked PE</b>\n", @$t0
.printf /D "<b>---------------------------------------------------------------------------</b>\n"
}
.else
{
.printf /D "-------------------------------------------------------------------------------------------------------------------------------------\n"
.printf /D "Process: ${processes_tok} base: %x -> Possible injected or unpacked PE, based on the dos header message: This program cannot...\n", @$t0
.printf /D "--------------------------------------------------------------------------------------------------------------------------------------\n"
}
}
}
}
r stage = 0
}
}
}
r stage = 0
}
}
ad stage
ad temp
ad temp2
ad temp3
ad isPossiblePE
ad isDosMessageBased
ad prev1
ad prev2
ad baseaddr
ad baseaddrlen
}