SNMPc: Fun with SEH

Recently I found a stack based buffer overflow in Caste Rock Computing’s SNMPc Enterprise Edition 9 & 10 software; details here if you want to read my disclosure info. Now, BOFs are relatively easy to identify, and old school vanilla EIP BOFs are even easier to write exploits for, however this time I encountered something which I haven’t needed to worry about before; the Structured Exception Handler (SEH). Because this was something different for me, I thought I may as well do a write-up about how I went about exploiting the software so that I can reference it in the future, and so that maybe someone out there may learn something new.

So what is SEH? I’ll let you do some googling for the full details, however the short version is that it is a Windows mechanism which is designed to catch exceptions and tell the operating system to search through a list of registers which are suitable for closing the program nicely. There are two records we need to manipulate on the stack in order to control the execution process, and that is the Exception Registration Record (SEH) and the Next Exception Registration Record (nSEH). Let’s get our hands dirty so that it all makes sense.

First things first, let’s get SNMPc to crash by creating a mapping file with a large buffer and import the created file into SNMPc. Our POC will look like this:

In the SNMPc Management Console, choose “File > Import > Map Objects From Text File...“, attach Immunity Debugger to the “nodeimp.exe” process, and choose the ‘evilmap.csv‘ file which our POC exploit has created. Now that the console has crashed, use “Alt+S” to view the SEH chain and pass the exception to the program with "Shift+F9" until you see that we have overwritten the SEH record with our buffer.

Now it’s time to zero in and find our offset where we are overwriting the SEH record. We’ll use the tried and tested method of generating a pattern with metasploit’s pattern_create tool as follows:

Now add the created pattern to the POC script, create the evilmap.csv file, import the file into the console, pass the exception to the program until you see the SEH record overwritten. Now let’s take a look at our SEH chain by using mona’s findmsp script.

As we can see, we now have our offset of 2064, however it’s not as simple as just setting our buffer to this length to overwrite SEH. Remember how I mentioned we have a SEH and nSEH? As the Windows stack grows downwards, we need to make sure we take nSEH into account as it will be hit first. Let’s update our POC script to reflect this.

Following our previous testing process, we can now see that we are overwriting SEH with our 4 bytes of C characters.

So what next? We haven’t overwritten EIP, so how do we take control of the process post the handler? Enter stage left POP POP RET. By using a POP POP RET instruction we can force the handler to put the address of nSEH into EIP, thus controlling execution. As always, mona is our friend and will find pointers with POP POP RET by issuing the command !mona seh.

I have chosen to use the address 0x100e3c05 in this case as it doesn’t contain any null bytes such as those in the previous two results. Let’s update our POC script, follow the bouncing ball for our test, and add a breakpoint at our SEH address so we can understand what POP POP RET is doing to our stack.

As you can see, we successfully hit our breakpoint:

Now, if we step through the POP POP RET with F7, we can see we jump straight to our B characters in nSEH, which is followed by SEH, then followed by our buffer of D characters.

The logical next step is to somehow get to our buffer of D characters so that we can execute some shellcode. So how do we do this? We can see that we need to jump forward 5 bytes. If you press ‘space’ in Immunity, an “Assemble at 0018F584” box appears which allows us to jump to the address we want to go to, which, in our case is 0x0018F58D. Enter jmp 0018F58D and hit ‘Assemble’, which will give us the short jmp op code of EB 07 which we can use in nSEH to get to our D characters.

Now that we have control of program execution, let’s update our POC script to reflect the short jmp and add some shellcode to execute calc.exe on the target host. We generate the shellcode for calc winexec with the following: msfvenom —platform windows -p windows/exec cmd=calc.exe -b "\x00\x0a\x0d" -f c

A Wild Calc Appears!!!! Until next time, tight lines and happy hacking.