BanMe
December 6th, 2010, 11:14
I counter-agree with indy and (delta/evaluator) in that,I agree a more accurate description of this is in order but that if you know asm you should be able to tell what it does..
its a length disasm engine with code to data graphing capabilities..
the way its built is like a service
GCBE:: is the 'defaulted to' entry point and it requires eax equals the value of the called function, this can be seen here..
Code:
GCBE::
; GPE Services
test eax,eax
jz QueryOpcodeSize
dec eax
jz QueryPrefixLength
dec eax
jz GpParse
dec eax
jz GpTrace
dec eax
jz GpFastCheckIpBelongToSnapshot
dec eax
jz GpCheckIpBelongToSnapshot
dec eax
jz GpFindCallerBelongToSnapshot
dec eax
jz GpSearchRoutineEntry
dec eax
jz GpQueryRoutineArgsNumber
dec eax
; GCBE service.
jz GpBuildGraph
mov eax,STATUS_INVALID_PARAMETER
ret
%GET_GRAPH_REFERENCE
assume fs:nothing
the test cases are really what illustrate the usage of this functionality and luckily I've been keeping track of good ol Indy
so I will provide what I have..
Test 1..args count and address
Code:
.686p
.model flat, stdcall
option casemap :none
include \masm32\include\ntdll.inc
includelib \masm32\lib\ntdll.lib
.code
include Engine.inc
%NTERR macro
.if Eax
Int 3
.endif
endm
; 10 args
_imp__RtlCreateUserThread proto \
ProcessHandle:HANDLE, \
SecurityDescriptor:PSECURITY_DESCRIPTOR, \
CreateSuspended:BOOLEAN, \
ZeroBits:ULONG, \
SizeOfStackReserve:ULONG, \
SizeOfStackCommit:ULONG, \
InitialEip:ULONG, \
nitialValueInStack:ULONG, \
OutThreadHandle:PHANDLE, \
OutClientId:PCLIENT_ID
$Msg CHAR "Address: 0x%p, Args: %u", 13, 10, 0
Ep proc
Local GpBase:PVOID, GpSize:ULONG
Local GpLimit:PVOID
Local ArgsCount:ULONG
mov GpBase,NULL
mov GpSize,4*X86_PAGE_SIZE
invoke ZwAllocateVirtualMemory, NtCurrentProcess, addr GpBase, 0, addr GpSize, MEM_COMMIT, PAGE_READWRITE
%NTERR
mov ecx,GpBase
lea edx,GpLimit
mov ebx,dword ptr [_imp__RtlCreateUserThread]
mov GpLimit,ecx
push eax
push eax
push eax
push eax
push eax
push eax
push edx
push ebx
mov eax,GP_PARSE;parse the region in question ebx
Call GP
%NTERR
lea ecx,ArgsCount
push ecx
push GpBase
mov eax,GP_QUERY_ROUTINE_ARGS_NUMBER
Call GP
%NTERR
invoke DbgPrint, addr $Msg, Ebx, ArgsCount
ret
Ep endp
end Ep
Test 2:Whats loading?
Code:
.686p
.model flat, stdcall
option casemap :none
include \masm32\include\ntdll.inc
includelib \masm32\lib\ntdll.lib
include \masm32\include\kernel32.inc
includelib \masm32\lib\kernel32.lib
.code GPECODE
include ..\Bin\Gpe.inc
%NTERR macro
.if Eax
Int 3
.endif
endm
%APIERR macro
.if !Eax
Int 3
.endif
endm
Public gChainDispatch
Public gLoadLibraryArg
.data
gSnapshot GP_SNAPSHOT <>
gChainDispatch PVOID ?
gLoadLibraryArg PSTR ?
.code
LoadLibrary2ndDispatch proc C
pushad
invoke DbgPrint, gLoadLibraryArg
popad
jmp gChainDispatch
LoadLibrary2ndDispatch endp
LdrpManifestProberRoutine proc DllBase:PVOID, FullDllPath:PCWSTR, ActivationContext:PVOID
Local Caller:GP_CALLER
lea eax,Caller
push eax
push UserMode
push NULL
push offset gSnapshot
%GPCALL GP_FIND_CALLER_BELONG_TO_SNAPSHOT
.if !Eax
mov edx,Caller.Frame ; ~PspCreateProcess()
lea ecx,LoadLibrary2ndDispatch
mov edx,STACK_FRAME.Next[edx]
xchg STACK_FRAME.Ip[edx],ecx
mov gChainDispatch,ecx
mov edx,dword ptr [edx + sizeof(STACK_FRAME)] ; Arg.
mov gLoadLibraryArg,edx
.endif
xor eax,eax
ret
LdrpManifestProberRoutine endp
LdrSetDllManifestProber proto :PVOID
_imp__LoadLibraryA proto :PSTR
$Dll CHAR "psapi.dll",0
Ep proc
Local GpSize:ULONG
Local OldProtect:ULONG
mov gSnapshot.GpBase,NULL
mov GpSize,1000H * X86_PAGE_SIZE
invoke ZwAllocateVirtualMemory, NtCurrentProcess, addr gSnapshot.GpBase, 0, addr GpSize, MEM_COMMIT, PAGE_READWRITE
mov ebx,gSnapshot.GpBase
%NTERR
add gSnapshot.GpBase,0FFFH * X86_PAGE_SIZE
mov GpSize,X86_PAGE_SIZE
invoke ZwProtectVirtualMemory, NtCurrentProcess, addr gSnapshot.GpBase, addr GpSize, PAGE_NOACCESS, addr OldProtect
%NTERR
mov gSnapshot.GpLimit,ebx
mov gSnapshot.GpBase,ebx
lea ecx,gSnapshot.GpLimit
push eax
push eax
push eax
push eax
push eax
push 1
push GCBE_PARSE_SEPARATE
push ecx
push dword ptr [_imp__LoadLibraryA]
%GPCALL GP_PARSE
%NTERR
invoke LdrSetDllManifestProber, offset LdrpManifestProberRoutine
invoke LoadLibrary, addr $Dll
%APIERR
ret
Ep endp
end Ep
test :3 Parsing a function to find a undocumented symbol...
exemplifies Parsing Tracing find undocumented entry and num of args..
Code:
.686p
.model flat, stdcall
option casemap :none
include \masm32\include\ntdll.inc
includelib \masm32\lib\ntdll.lib
_imp__LdrLoadDll proto :PWCHAR, :PULONG, :PUNICODE_STRING, :PHANDLE
.code GPECODE
include ..\Bin\Gpe.inc
%NTERR macro
.if Eax
Int 3
.endif
endm
%APIERR macro
.if !Eax
Int 3
.endif
endm
.code
GCBE_PARSE_NL_UNLIMITED equ -1
TRACE_DATA struct
ScanBase PVOID ?
ScanLimit PVOID ?
Message PSTR ?
MsgLength ULONG ?
Gp PVOID ?
TRACE_DATA ends
PTRACE_DATA typedef ptr TRACE_DATA
TraceCallback proc uses ebx esi edi GpEntry:PVOID, TraceData:PTRACE_DATA
mov eax,GpEntry
test dword ptr [eax + EhEntryType],TYPE_MASK
mov ebx,TraceData
jne Exit ; !HEADER_TYPE_LINE
assume eax:PBLOCK_HEADER
mov esi,[eax].Address
mov edi,[eax]._Size
assume ebx:PTRACE_DATA
Ip:
push esi ; Ip
%GPCALL GP_LDE ; LDE()
cmp al,5
jne @f
cmp byte ptr [esi],68H ; push imm32
mov edx,dword ptr [esi + 1] ; ref.
jne @f
cmp [ebx].ScanBase,edx
ja @f
cmp [ebx].ScanLimit,edx
jbe @f
push esi
push edi
mov esi,edx
mov edi,[ebx].Message
mov ecx,[ebx].MsgLength
cld
repe cmpsb
pop edi
pop esi
jne @f
mov eax,GpEntry
mov [ebx].Gp,eax
jmp Exit
@@:
add esi,eax
sub edi,eax
ja Ip
Exit:
xor eax,eax
ret
TraceCallback endp
$Message CHAR "LdrpResolveDllName", 0
$Ldrp CHAR "Def.: LdrpResolveDllName(), Address: 0x%p, Arg's: %x", 13, 10, 0
assume fs:nothing
Ep proc
Local GpSize:ULONG
Local Snapshot:GP_SNAPSHOT
Local ArgsCount:ULONG
Local OldProtect:ULONG
Local TraceData:TRACE_DATA
Local Gp:PVOID
mov Snapshot.GpBase,NULL
mov GpSize,1000H * X86_PAGE_SIZE
invoke ZwAllocateVirtualMemory, NtCurrentProcess, addr Snapshot.GpBase, 0, addr GpSize, MEM_COMMIT, PAGE_READWRITE
mov ebx,Snapshot.GpBase
%NTERR
add Snapshot.GpBase,0FFFH * X86_PAGE_SIZE
mov GpSize,X86_PAGE_SIZE
invoke ZwProtectVirtualMemory, NtCurrentProcess, addr Snapshot.GpBase, addr GpSize, PAGE_NOACCESS, addr OldProtect
%NTERR
mov Snapshot.GpLimit,ebx
mov Snapshot.GpBase,ebx
lea ecx,Snapshot.GpLimit
push eax
push eax
push eax
push eax
push eax
push GCBE_PARSE_NL_UNLIMITED
push GCBE_PARSE_DISCLOSURE
push ecx
push dword ptr [_imp__LdrLoadDll]
%GPCALL GP_PARSE
%NTERR
mov eax,fs:[TEB.Peb]
mov eax,PEB.Ldr[eax]
mov eax,PEB_LDR_DATA.InLoadOrderModuleList.Flink[eax]
mov eax,LDR_DATA_TABLE_ENTRY.InLoadOrderModuleList.Flink[eax]
mov esi,LDR_DATA_TABLE_ENTRY.DllBase[eax] ; ntdll.dll
invoke RtlImageNtHeader, Esi
%APIERR
mov ecx,IMAGE_NT_HEADERS.OptionalHeader.BaseOfCode[eax]
mov edx,IMAGE_NT_HEADERS.OptionalHeader.SizeOfCode[eax]
mov TraceData.Gp,NULL
add ecx,esi
lea edx,[edx + esi - sizeof $Message]
mov TraceData.Message,offset $Message
mov TraceData.MsgLength,sizeof $Message
mov TraceData.ScanBase,ecx
mov TraceData.ScanLimit,edx
lea ecx,TraceData
lea edx,TraceCallback
push ecx
push edx
push ebx
%GPCALL GP_TRACE
%NTERR
.if TraceData.Gp == NULL
Int 3
.endif
lea ecx,Gp
lea edx,Snapshot
push ecx
push eax
push eax
push 1
push eax
push TraceData.Gp
push edx
%GPCALL GP_SEARCH_ROUTINE_ENTRY
%NTERR
mov ebx,Gp ; ref.
mov eax,dword ptr [ebx + EhEntryType]
and eax,TYPE_MASK
.if Eax != HEADER_TYPE_CALL
Int 3
.endif
assume ebx:PCALL_HEADER
mov ecx,[ebx].BranchLink
lea eax,ArgsCount
and ecx,NOT(TYPE_MASK)
push eax
push ecx
%GPCALL GP_QUERY_ROUTINE_ARGS_NUMBER
%NTERR
invoke DbgPrint, addr $Ldrp, [ebx].BranchAddress, ArgsCount
ret
Ep endp
end Ep
test 4:real function length
Code:
.686p
.model flat, stdcall
option casemap :none
include \masm32\include\ntdll.inc
includelib \masm32\lib\ntdll.lib
.code GPECODE
include ..\Bin\Gpe.inc
GCBE_PARSE_NL_UNLIMITED equ -1
%NTERR macro
.if Eax
Int 3
.endif
endm
.data
pRoutine PVOID offset GPE ; Àäðåñ ðàçáèðàåìîé ïðîöåäóðû.
NestingLevel ULONG GCBE_PARSE_NL_UNLIMITED ; Óðîâåíü âëîæåííîñòè. Äëÿ îäíîé ïðîöåäóðû 1.
.code
$Msg CHAR "0x%X", 13, 10, 0
assume fs:nothing
Ep proc
Local GpBase:PVOID, GpLimit:PVOID, GpSize:ULONG
Local OldProtect:ULONG
mov GpBase,NULL
mov GpSize,1000H * X86_PAGE_SIZE
invoke ZwAllocateVirtualMemory, NtCurrentProcess, addr GpBase, 0, addr GpSize, MEM_COMMIT, PAGE_READWRITE
mov ebx,GpBase
%NTERR
add GpBase,0FFFH * X86_PAGE_SIZE
mov GpSize,X86_PAGE_SIZE
invoke ZwProtectVirtualMemory, NtCurrentProcess, addr GpBase, addr GpSize, PAGE_NOACCESS, addr OldProtect
%NTERR
mov GpLimit,ebx
mov GpBase,ebx
lea ecx,GpLimit
push eax
push eax
push eax
push eax
push eax
push NestingLevel
push GCBE_PARSE_DISCLOSURE
push ecx
push pRoutine
%GPCALL GP_PARSE
%NTERR
xor ebx,ebx
mov esi,GpBase
@@:
test dword ptr [esi + EhEntryType],TYPE_MASK
.if Zero? ; Line
add ebx,dword ptr [esi + EhSize]
.else
push dword ptr [esi + EhAddress]
%GPCALL GP_LDE
add ebx,eax
.endif
add esi,ENTRY_HEADER_SIZE
cmp GpLimit,esi
ja @b
invoke DbgPrint, addr $Msg, Ebx
ret
Ep endp
end Ep
I do agree with indy that no better example of what something does is illustrated in the source, though 'picking' it out for some is difficult..
regards BanMe
also if you didnt read the code be aware that it is from a older version of GCBE called GPE.. but it looks like all that code migrated so it should work with but a few tweaks.. enjoy..