Quote:
[Originally Posted by "Indy"]
Easier to explain by examples
|
I like documentation, something concrete to understand and work with.
IDP 3.0 (User Mode).
Capturing Code with pointers is the Goal of IDP.
This advanced technology allows you to capture code execution without modification. For the first time this technique was used to capture the SST(System Service Table), later it was used several times, after which it was a workable concept.
Capturing SST works as follows:
In the target SST table reference arguments (ArgumentTable) cases discharges are not valid. The table element is addressed in pairs, one of its indexes, and the other containing
the base tables, pre-loaded from the link in SST. When referring to the table to extract from it the arguments from the user stack. Callback gets the address of instruction that caused the execution, the address to which there was context at the time of the exception. Loading in register address of the table of the original address it, OT flazhek usual TF and executed restart instructions. About increment is a valid (original) address and after the execution of the instructions generated by the trace exception. From this place is traced to before entering the service processor, and then tracer SC stops and the trade continues to run normally about. In this case, created the conditions for the emergence of exception (not valid pointer), after which the code traced to the target location.
These three mechanisms are at the heart of the technique.
The address to which it should occur on re-treatment start up instructions in two ways - to change registers (RGP if used), or change the segment, settlement redstvom change the segment registers. About engine for the first method requires a full disassembler. Used as a simple reboot segments in a universal way.
Procedural branch in the trace code to
miss. If procedural branching is pre
matters of procedure, target code, then the replacement
the return address on the stack immediately after the branching (mezhsegm
entnye branching quite rare in yuzermode). Return and
s procedure will be performed at the new address. At the same mo
zhno roll back to the original address, or prezh
de downloading not a valid address to handle the exception, n
After restarting Eip. If space is available to the target of the chain
a stack frame (formed sequence embedded
adjoint procedural branches), you must perform
their sweep (baktreys) and replace the return address of at
the necessary procedures, as described above. Used di
zassemblirovanie each instruction in the tracer
FRI (see Op.asm, IsCallOpcode ()).
-
For example, to capture LdrpGetProcedureAddress () can and
spolzovat different methods, consider capturing describe
Second technique. To check the validity psevdohendla fashion
To use the procedure LdrpCheckForLoadedDllHandle (
). This procedure scans byzy data
loader to search for base module in it. Previously
checks the value of the variable LdrpLoadedDllHandleCac
he, to handle the module remains PLDR_DATA_TABLE_
ENTRY, which was last accessed (such
discharging caching to speed up the search.)
Perform destruction pointer variable LdrpLoadedD
llHandleCache. When removing the module from the database handle
it by reference in this variable for future ref
eniya tested it with an exception basis (see
\ Win2k \ private \ ntos \ dll \ ldrsnap.c):
mov eax, dword ptr ds: [LdrpLoadedDllHandleCache]
...
cmp dword ptr ds: [eax + 18], esi
It is processed by means of the engine and the need for
generation stop and subsequent processing. Dispatcher
Exceptions may have two options: replace
the return address of the procedure (located in the stack
frame addressable register Ebp) to your code (or the n
e valid address), or to trace the entire procedure. Last
e in the context of this Eip flow on return from the procedure
Rea will point to the body in the previous procedure, in this
dimensional case is LdrpGetProcedureAddress (). When the product
ydet return to this procedure and begin platoon TF tra
ssirovat code. At each step the type of statement
and. If this is a procedural branching, then tracing it
then replace the return address on the stack, precede
flax kept current, then stop the trace. T
Ed will perform the procedure, followed by a return of Mr.
of procedure on a replacement address. Load the Eip Saved
Anenii address. Thus the procedure is passed:
Code:
LdrpGetProcedureAddress:
...
call LdrpCheckForLoadedDllHandle; Break
...
call RtlImageDirectoryEntryToData
...
call LdrpSnapThunk
...
When you trace the target location is reached,
Tracing stops. Through this you can pin
rolirovat code below and up the chain of stack frames.
This is not the only solution that can be applied naprime
p destroying structures in the database loader for DOS
tizheniya similar results. Music can be used
ifikatsiya (done LdrpRunInitializeRoutines () esl
and dumped in the descriptor flazhek LDRP_ENTRY_PROCESSED fashion
la, etc., but this does not apply to a subject.
-
In some cases, this technique avoids Zats
iklivaniya and recursive calls. For example when capturing
cookies. In XP, the software protection (DEP) stack
overflow via cookies. Should consider
mechanism in more detail. At the beginning of the execution vulnerability
procedures stored in the stack variable
Code:
__ security_cookie:
RtlCreateUserThread:
push 324
push 7C92E140
call _SEH_prolog
mov eax, dword ptr ds: [__security_cookie]
mov dword ptr ss: [ebp-1C], eax
...
mov ecx, dword ptr ss: [ebp-1C]
call __ security_check_cookie
call _SEH_epilog
ret 28
Before returning from the stored procedure in the stack values
tion compared with the value of the variable, and if they are from
differ, or the principal part of the stored ex
ichna-zero exception is generated
Code:
STATUS_STACK_BUFFER_OVERRUN:
__security_check_cookie:
cmp ecx, dword ptr ds: [__security_cookie]
jnz __ report_gsfailure
test ecx, FFFF0000
jnz __ report_gsfailure
ret
__report_gsfailure () saves the thread context and calling
AET final exception handler through RtlUnh
andledExceptionFilter (). It is notification
debugger through DbgPrint () and then vDbgPrintExWi
thPrefix (). The latter function is protected by cookies. If used
USED capture cookies loaded into the upper part of the transition
variable __ security_cookie value other than zero (ie
always on return of the many functions it calls __
report_gsfailure ()), this will result in a recursive call
m to the exhaustion of the stack and the process will be completed
en kernel. To prevent this situation, one can use
zovat technique IDP. In early RtlUnhandledExceptionFil
ter2 () reads the command line (TEB.Peb ->PEB.ProcessParameters ->RTL_USER_PROCESS_PARAMETERS.CommandLine.Buffer):
Code:
RtlUnhandledExceptionFilter2:
push 1C
push 7C967288
call _SEH_prolog
mov eax, dword ptr fs: [18]
mov eax, dword ptr ds: [eax +30]
mov eax, dword ptr ds: [eax +10]
mov ebx, dword ptr ds: [eax +44]
...
PEB.ProcessParameters by breaking this code
can be captured. At the same time it calls Dispatch
EPA exemptions that will get the thread context (the stack
ew frame, addressable register Ebp) sufficient to
return to the code after the call to __ security_check_cookie (
). On return from the many functions of management will have sex
uchat Manager exceptions. Similarly one was
Oba to capture _SEH_prolog () and _SEH_epilog (). About
Fs nulit segment register and handle the exception
accessing the TEB. The problem is to use
and fast system calls that restore AD
one register to the default value. A solution could be
Softpedia setting breakpoints on KiFastSystemCallRet ().
-
Description of the engine.
Capture engine links destruction pointers.
Suppose you have a variable that contains a pointer to about
blasts of known size. Address of this area
ty formed offset within the first 16 pages
address space, which is loaded into the variable
w. LDT descriptor is created in a database, which is in a scoop
upnosti offset address of the target memory.
Before applying to this memory area, a reference to not
e in the variable vector must be registered
exception handler is the last in the chain (after the dispatcher
Chera engine). When an appeal to the Memory of
Yachi, referred to by the variable exception occurs
tion. Exception Manager engine on the basis of the address (the
blasts memory) which was handling the determinant
t corresponding to this segment selector, download ez
on a segment registers, vzvedet flazhek TF and pass
control to the next handler in the chain. In this case,
handler receives an error code IDP_BREAKPOINT. Receiving
the message handler to complete processing,
Perform return to the interrupted code. There will appeal
e to the area of memory, formed the base offset and seg
cient. After that, there a trace exception
required to restore the segment registers. About
brabotchik engine restore selectors and flags register
in, and then passes control to the next processing
Chick. This is the second soobytie handler receives its code I
DP_SINGLE_STEP. From this place can be started Far
eyshaya processing (routing, etc). Information about oblas
ty of memory associated with a variable controller can extraction
Grigorievich of structure SEGMENT_ENTRY, a pointer to that on
hoditsya at TEB at offset 0xFFC. Displacement of memory
ti is formed so, that the two regions are projected
uemye the inaccessible page do not intersect. This makes it
The will record the number of areas of memory formation
Rui for each of them the handle.
Code:
0x00000000 -> + ----- SEG1 ---- + N
| | O
___ | |
0x00000SSS -> + --------------- + A ----.
| 1 | C | O
| 2 | C | F
| 3 | E | F
+ --------------- + S | S
| | S | E
0x00010000 -> + --------------- + - | T
___ | | BASE V
0xBBBBB000 -> + ----- SEG2 ---- + ----> +
___ | | | LINE ADDR
0xBBBBBSSS -> + --------------- + <----- '
& | 1 | R
0x00000FFF | 2 | W
| 3 | E
+ --------------- + -
| |
Thus engine monitors access to certain
memory areas, making the notification party code
when you access this area. It is not the purpose of submanifold
ene data. To do this, allocate memory in early
address space (somewhere below the target memory region
ty) and create a descriptor in the LDT with a base equal to the difference
and address of the target area and the underlying buffer Changeling
nyaemymi data. Further, when an exception occurs cl
eduet load selector handle is created in the Segment
entnye registers, will appeal to the buffer.
-
Protection Manager and trace deadloka.
Custom handler receives an mp
assirovochnom exception in System Manager ("If
oznikaet exception # DB (STATUS_SINGLE_STEP), then the pin
ekste flow on the stack and the current sbrasyvaets
I TF (Trap Flag). For other exceptions other than # D
B (STATUS_SINGLE_STEP) at the moment of which
was armed, TF, login manager exceptions (KiUserExce
ptionDispatcher () is performed with a cocked TF. After hours
it generates a trace exception (# DB) and a TF
brasyvaetsya. "

. If the custom handler is not pr
overyaet address stop the trace manager Bud
em run to capture the critical section RtlpCallo
utEntryLock in RtlCallVectoredExceptionHandlers (). Proi
go recursive calls dispetera exceptions Trace
renormalization RtlEnterCriticalSection (RtlpCalloutEntryLock) sd
elaet not correct box RTL_CRITICAL_SECTION.LockCoun
t, and the next time kritichiskuyu section occured
t deadlok, trade opening event will be waiting for the alarm. Rear
avoid this exception dispatcher engine
checks the address of the trace exception and if it is a
shows a second user of the system control (optional
mined dynamically, if captured splice Manager
ingom eg jump to the handler, the second statement
First is the following for branching), the trace pr
ekraschaetsya and control returns to the dispatcher.
-
Using a pair of segments.
Instructions Movs copies data from a segment of Ds: [Esi] in
segment Es: [Edi]. Prefixes redefined
change of segment segment from which to copy e
TED. This statement requires special handling. T
ak for other instructions reloaded registration
Ry Fs, Es, Ds and Gs (reset scheduler) for Movs
restarts registers depending on
board data transfer. If you record in
captured locations, the only restarts
Register Es. If you are reading from the captured region
asti memory, determined to redefine the prefix
edeleniya segments. If not, then reboot re
giste Ds. If defined segment prefix Es, Reboot
uzhaetsya only Es. Otherwise reload registers Fs,
Ds and Gs.
Code segments (Cs) and the stack (Ss) is not overridden. Nap
Example instruction Push dword ptr Ds: [Eax] uses IR
a segment, stack (Ss) and data (Ds), the latter can be
Th overridden. Capture the stack is used. Pereop
definiteness of the code segment is not possible. Typically, the data and
one separated and need to capture the links, addressable
th through the register Cs rare. To capture the reference strain
Uru should substitute a pointer to it in a variable.
-
The following situations are not allowed:
Capture the reference that is used in the Grain
otki exceptions. Such seizure TEB and PEB in links e
quiet structures will lead to recursive call manager
until out of the stack, as RtlDispatchException () on
raschaetsya to these links. To work around this should be ful
lnit capture system control exceptions tough
modification of its code. Convenient replacement atomic displacements
I Call RtlDispatchException instructions on Manager
engine. If you can write to the kernel, you can
to change the link to the system manager in the variable poison
Mr. KeUserExceptionDispatcher.
Capture a memory area whose address Provence
satisfies the code. For example, capture the data in the boot
reference to it, which is in Peb.Ldr will
hang. Thread will execute an infinite loop.
Code:
LdrpCheckForLoadedDll ():
...
7C916A49:
cmp edi, esi
je short 7C916A7C
mov ebx, edi
mov edi, dword ptr ds: [edi]
cmp dword ptr ds: [ebx +8], 0
je short 7C916A49
push 1
lea eax, dword ptr ds: [ebx +24]
push eax
lea eax, dword ptr ss: [ebp-240]
push eax
call ntdll.RtlEqualUnicodeString
test al, al
je short 7C916A49
...
Edi - points to the current item. Esi - decrees
cates of the list (PEB_LDR_DATA.InLoadOrderModuleLi
st.Flink), ie [Peb.Ldr] + 0xC, respectively PICKUP
achen not valid and there is no reference to it in a doubly
nnom list. Pointers never coincide, since one
Institute of them changed when capturing reference.
Link must not be passed to the kernel or ispolzovat
sya them (eg PEB.LoaderLock change kernel when completed
shenii thread). Otherwise, an exception is thrown in the nucleus and serv
research fails.
-
A simple example. The database loader (Ldr) has
many references, such as a pointer to yunikodovskoe and
me module (LDR_DATA_TABLE_ENTRY.BaseDllName.Buffer). You
suppl capture this pointer of the first descriptor can
module in the list means the engine, and then trying to s
agruzit sided module with LoadLibraryA (). Dee
spetcher exceptions will be called multiple times, this field
loader is used to search for the module's name. And
Exception occurs Inside RtlEqualUnicodeString () and on
For instructions:
mov cx, word ptr ds: [edi]; UNICODE "ntdll.dll"
From the register in the context Ebp can get the source of the Criminal Code
azatel baktreysa to obtain and execute its sequence
sequence of calls:
Code:
ntdll.RtlEqualUnicodeString
ntdll._LdrpCheckForLoadedDll @ 20
ntdll._LdrpLoadImportModule @ 20
ntdll._LdrpHandleOneNewFormatImportDescriptor @ 20
ntdll._LdrpHandleNewFormatImportDescriptors @ 16
ntdll._LdrpWalkImportDescriptor @ 8
ntdll._LdrpLoadDll @ 24
kernel32._LdrLoadDll @ 16
kernel32.LoadLibraryExW
kernel32.LoadLibraryExA
kernel32.LoadLibraryA
When comparing the module names for each character name n
roiskhodit stop. For example, to capture the code after Call
Peninsula LoadLibraryA () should perform baktreys find f
Reim with a pointer to this function and replace it addresses
with the return. If the exception is a stub manager
oh, that after working the download completes successfully.
-
Call models.
Appeal to the engine is done by calling the beginning
la code. The register number that indicates Eax
service. Dvizhek he cleans the stack parameters. Use
are produced the following services:
Initializing engine.
Code:
# Define IDP_INITIALIZE_ENGINE 0x00000000
typedef NTSTATUS (* PENTRY) (
);
When initializing generated two exceptions, the first
STATUS_PRIVILEGED_INSTRUCTION (# GP), after the tracer
ovochnoe STATUS_SINGLE_STEP (# DB). This internal Exclusive
eniya, they are processed by the engine.
Capture link.
Code:
# Define IDP_ADD_REFERENCE 0x00000001
typedef NTSTATUS (* PENTRY) (
IN OUT PVOID * Reference
IN ULONG SpaceSize
);
Registration vector exception handler.
Code:
#Define IDP_ADD_VEH 0x00000002
typedef PVOID (* PENTRY) (
IN ULONG First, / / Zero.
IN PVECTORED_EXCEPTION_HANDLER Handler
);
typedef LONG (* PVECTORED_EXCEPTION_HANDLER) (
IN OUT PEXCEPTION_POINTERS * ExceptionInformation
);
Polzovatelsy vector exception handler should
be set as follows in the chain, after the manager
Exceptions engine. This is achieved by transmitting the first pa
eter zero.
To unregister the exception handler.
Code:
# Define IDP_REMOVE_VEH 0x00000003
typedef ULONG (* PENTRY) (
IN PVOID Handle
);
Getting an address on behalf of the export or hash.
Code:
#Define IDP_QUERY_ENTRY 0x00000004
typedef NTSTATUS (* PENTRY) (
IN PVOID ImageBase OPTIONAL,
IN PVOID HashOrFunctionName,
IN PCOMPUTE_HASH_ROUTINE HashRoutine OPTIONAL,
IN ULONG PartialCrc,
OUT * PVOID Entry
);
typedef ULONG (* PCOMPUTE_HASH_ROUTINE) (
IN ULONG UserParameter,
IN PVOID Buffer,
IN ULONG Length
);
If kalbek computes hash is not set, then the second param
mp is seen as a pointer to the name of the export. If
Base module is specified, the isplzuetsya ntdll.dll
Kalbek should return the register Eax hash for a string.
Gets addresses exports Crc32 names.
Code:
# Define IDP_QUERY_ENTRIES 0x00000005
typedef NTSTATUS (* PENTRY) (
IN PVOID ImageBase OPTIONAL,
IN ULONG PartialCrc,
IN PULONG Crc32List,
OUT * PVOID EntriesList
);
Marker of the end of the list is zero. Transferred ex
port module is calculated for each name Crc32 RSR
dstvom ntdll! RtlComputeCrc32, a comparison is made with
value in the array. If the values are equal, running
fetch the next element of the array.
Structure SEGMENT_ENTRY describes segment to which
treatment was:
Code:
typedef struct _SEGMENT_ENTRY {
PVOID SegmentBase;
PVOID SegmentLimit;
PVOID SegmentAddress;
PVOID Reference;
} SEGMENT_ENTRY, * PSEGMENT_ENTRY;
Link to SEGMENT_ENTRY TEB is at offset:
Code:
# Define IDP_SEGMENT_ENTRY_OFFSET 0x00000FFC
And is part of the structure, which describes the stop:
Code:
typedef struct _THREAD_STATE {
ULONG rEFlags;
PSEGMENT_ENTRY Segment;
} THREAD_, * PTHREAD_STATE;
The offset is in TEB:
Code:
# Define IDP_THREAD_STATE_OFFSET 0x00000FF8
Event codes VEH:
Code:
# Define IDP_BREAKPOINT 0x80FE0001 / / Stop.
# Define IDP_SINGLE_STEP 0x80FE0002 / / Trace.
The style of writing is dvizhek mikodom (MI), ie
code with variable count and can be otmorflen.
December 2009, VirusTech.org