P3nro5e · 2015/07/10 10:58
0x00 Mona 2 Preface & Preparation
Mona 2 is a very useful plug-in developed by Corelan Team. Originally written for Immunity Debugger, it now works with the WinDbg Debugger.
You will need to install some tools for WinDbg x86 and WinDbg X64:
Install Python 2.7 (available here).
The x86 and X64 versions of the tools are installed in different directories, such as C :\python27(32) and C :\python27.
Download the correct zip package from here (please download the pykD-0.2.0.29-python-2.7.zip package), then extract and run vcredist_x86.exe and vcredist_x64.exe.
Download two exe programs (x86 and X64) from here and execute them.
Download windbglib.py and mona.py from here and place them in the same directory as Windbg.exe.
The search path for symbols is as follows:
Through File→Symbol File Path
The input
SRV*C:\windbgsymbols*http://msdl.microsoft.com/download/symbols
Copy the code
3. Save the Workspace (File→Save Workspace).
Run mona.py under WinDbg
Example of running mona.py with WinDbg:
1. Run the following command to load the PyKD plug-in
.load pykd.pyd
Copy the code
2. Run the mona command as follows:
! py monaCopy the code
Update mona input as follows:
! py mona updateCopy the code
0 x01 configuration
Working directory
In mona’s working directory, most of mona’s functions dump data into created files. We can specify a working directory, depending on the process name and ID specified by the format specifiers %p (process name) and % I (process ID) used.
For example, enter:
workingfolder "C:\mona_files\%p_%i"
Copy the code
Eliminate module
You can exclude specified modules by:
! mona config -set excluded_modules "module1.dll,module2.dll" ! mona config -add excluded_modules "module3.dll,module4.dll"Copy the code
The author
You can also set the author:
! mona config -set author KiuhnmCopy the code
This information can be used when producing metasploit-compatible output.
Focus on
If neither WinDbg nor Mona is wrong, try running WinDbg as an administrator.
0x02 Manual of Mona
You can find out more about Mona here.
sample
This example is from Mona’s manual. Now let’s specify the ECX values we control in the following code:
MOV EAX, [ECX]
CALL [EAX+58h]
Copy the code
We want to use the code to JMP to our shellcode (that is, we injected into the process of the code), its address in ESP + 4, so we need to call some of the above call instructions, such as “ADD ESP, 4 | RET”. The code above has a number of indirect actions:
(ECX = (p1) - > p2 p2 + h to p3, 58 "ADD ESP, 4 | RET"Copy the code
First we need to find P3:
! py mona config -set workingfolder c:\logs ! Py mona stackpivot -distance 4,4Copy the code
As a command allows you to use the offset range specified in the mix in stackpivots ~ Max find equivalent to ADD ESP, X | RET the pointer of the code, through the options – short min, Max to specify the offset range.
It has been found that pointer/address will be written to c:\logs\ stackPivot.
Now we have our P3 Pointers (lots of P3 Pointers!) , we also need to find P1:
! py mona find -type file -s "c:\logs\stackpivot.txt" -x * -offset 58 -level 2 -offsetlevel 2Copy the code
Here’s what those options mean:
Using the “-x *” option means that you “accept addresses in pages with any access level” (as in another example, using the “-x x” option means we’re only locating in the executable page).
“-level 2” specifies the level of instruction to operate indirectly. It tells Mona to find “A pointer (P1)to a pointer (P2)to a pointer (p3)”. The first two options (-type and -s) specify that ps must be a pointer, which is listed in the file “C :\logs\ stackPivot.
When the “-offsetLevel 2” and “-offset 58” options tell Mona to offset 58h for increment, the second pointer (p2) must point to the third pointer (p3).
Don’t worry if this example doesn’t give you a good idea of what it’s about. This example just shows you what you can do with the Mona plug-in in WinDbg. Of course, I admit that the syntax of this command is not very straightforward.
sample
The findwild command allows you to find a chain of instructions with a particular form. Consider the following example:
! mona findwild -s "push r32 # * # pop eax # inc eax # * # retn"Copy the code
The “-s” option specifies the chain shape:
Separate instructions with ‘#’
R32 is any 32-bit register
- Is any sequence of instructions
Optional parameters are as follows:
- -depth
<nr>
: maximum length of the chain - -b
<address>
: base address for the search - -t
<address>
: top address for the search - -all: Returns also chains which contain “bad” instructions, i.e. instructions that might break the chain (jumps, calls, etc…)
The chain of ROP
Mona can find ROP Gadgets and use them to construct ROP chains, but I won’t cover that in this section because I’m assuming you don’t know what ROP chains are or what ROP is. As I said before, don’t worry if this article is too much for you to understand. Feel free to study the next installment in this series.
0x03 Structured Exception Handling (SEH)
Exception handlers exist in the form of a single linked list that is associated with each thread. In general, the nodes of a linked list are assigned on the stack. A pointer at the beginning of a Thread Environment Block (TEB) points to the head of the list, so when code wants to add a new exception handler, a new node is added to the head and the position of the pointer in the TEB is changed to point to the new node.
Each node has the inherent _EXCEPTION_REGISTRATION_RECORD type and stores the address of the processor and a pointer to the next node in the list. Oddly enough, the “Next Pointer” on a node on the list is not null but is equivalent to 0xFFffFFFF.
The exact definition is as follows:
0:000> dt _EXCEPTION_REGISTRATION_RECORD ntdll! _EXCEPTION_REGISTRATION_RECORD +0x000 Next : Ptr32 _EXCEPTION_REGISTRATION_RECORD +0x004 Handler : Ptr32 _EXCEPTION_DISPOSITIONCopy the code
TEB can be accessed by segment-selective subfs (starting with fs:[0]), so you usually see the following code:
mov eax, dword ptr fs:[00000000h] ; retrieve the head
push eax ; save the old head
lea eax, [ebp-10h]
mov dword ptr fs:[00000000h], eax ; set the new head
.
.
.
mov ecx, dword ptr [ebp-10h] ; get the old head (NEXT field of the current head)
mov dword ptr fs:[00000000h], ecx ; restore the old head
Copy the code
The compiler usually registers a single global handle, which is aware of the area the program has executed (depending on a global variable) and behaves accordingly when it is called.
Because each thread has a different TEB, the operating system ensures that segments are selected by FS, which always references the exact TEB (that is, one of the current threads). The address of TEB is obtained by reading fs:[18h] that matches the Self region of TEB.
TEB information is listed as follows:
0:00 0 >! teb TEB at 7efdd000 ExceptionList: 003ef804 ----------------------- StackBase: 003f0000 StackLimit: 003ed000 SubSystemTib: 00000000 FiberData: 00001e00 ArbitraryUserPointer: 00000000 Self: 7efdd000 EnvironmentPointer: 00000000 ClientId: 00001644 . 00000914 RpcHandle: 00000000 Tls Storage: 7efdd02c PEB Address: 7efde000 LastErrorValue: 2 LastStatusValue: c0000034 Count Owned Locks: 0 HardErrorMode: 0Copy the code
Now we can verify that fs references TEB:
0:000> dg fs
P Si Gr Pr Lo
Sel Base Limit Type l ze an es ng Flags
---- -------- -------- ---------- - -- -- -- -- --------
0053 7efdd000 00000fff Data RW Ac 3 Bg By P Nl 000004f3
Copy the code
As we discussed earlier, fs:18h contains the address of TEB:
0:00 0 >? poi(fs:[18]) Evaluate expression: 2130563072 = 7efdd000Copy the code
Remember: POI dereferences a pointer and uses’? ‘to evaluate an expression. ExceptionList specifies the name of the structure to which the ExceptionList points:
0:000> dt nt! _NT_TIB ExceptionList ntdll! _NT_TIB +0x000 ExceptionList : Ptr32 _EXCEPTION_REGISTRATION_RECORDCopy the code
As we’ve already said, this means that each node will be an instance of _EXCEPTION_REGISTRATION_RECORD. Use! The slist command displays information about the entire list:
0:00 0 >! slist $teb _EXCEPTION_REGISTRATION_RECORD SLIST HEADER: +0x000 Alignment : 3f0000003ef804 +0x000 Next : 3ef804 +0x004 Depth : 0 +0x006 Sequence : 3f SLIST CONTENTS: 003ef804 +0x000 Next : 0x003ef850 _EXCEPTION_REGISTRATION_RECORD +0x004 Handler : 0x6d5da0d5 _EXCEPTION_DISPOSITION MSVCR120! _except_handler4+0 003ef850 +0x000 Next : 0x003ef89c _EXCEPTION_REGISTRATION_RECORD +0x004 Handler : 0x00271709 _EXCEPTION_DISPOSITION +0 003ef89c +0x000 Next : 0xffffffff _EXCEPTION_REGISTRATION_RECORD +0x004 Handler : 0x77e21985 _EXCEPTION_DISPOSITION ntdll! _except_handler4+0 ffffffff +0x000 Next : ???? +0x004 Handler : ???? Can't read memory at ffffffff, error 0Copy the code
Remember that $teb represents the address of the TEB.
Here is a more concise way to show information about the exception handling chain:
0:00 0 >! exchain 003ef804: MSVCR120! _except_handler4+0 (6d5da0d5) CRT scope 0, func: MSVCR120! doexit+116 (6d613b3b) 003ef850: exploitme3+1709 (00271709) 003ef89c: ntdll! _except_handler4+0 (77e21985) CRT scope 0, filter: ntdll! __RtlUserThreadStart+2e (77e21c78) func: ntdll! __RtlUserThreadStart+63 (77e238cb) We can also examine the exception handler chain manually: 0:000> dt 003ef804 _EXCEPTION_REGISTRATION_RECORD MSVCR120! _EXCEPTION_REGISTRATION_RECORD +0x000 Next : 0x003ef850 _EXCEPTION_REGISTRATION_RECORD +0x004 Handler : 0x6d5da0d5 _EXCEPTION_DISPOSITION MSVCR120! _except_handler4+0 0:000> dt 0x003ef850 _EXCEPTION_REGISTRATION_RECORD MSVCR120! _EXCEPTION_REGISTRATION_RECORD +0x000 Next : 0x003ef89c _EXCEPTION_REGISTRATION_RECORD +0x004 Handler : 0x00271709 _EXCEPTION_DISPOSITION +0 0:000> dt 0x003ef89c _EXCEPTION_REGISTRATION_RECORD MSVCR120! _EXCEPTION_REGISTRATION_RECORD +0x000 Next : 0xffffffff _EXCEPTION_REGISTRATION_RECORD +0x004 Handler : 0x77e21985 _EXCEPTION_DISPOSITION ntdll! _except_handler4+0Copy the code