Recently, I have decided to test my skills on creating exploit for some new vulnerability present publicly for which the exploitation code is not present. After searching many vulnerability on nvd.nist.gov database I have decided to try Buffer overflow on Windows software "Barcodewiz" CVE-2018-5221. More details on vulnerability here.
The software is a barcode creator with lots of feature like support of adding barcode to MS Office. The overflow exist in version <6.7 but the one that I am going to use is Barcode ActiveX control trail v6.5.
The owners's have already updated the version to recent vulnerability free version.
Detecting the issue
Once I installed the executable I click on "Barcode Properties" and prompt with following window.
From the CVE page I found out that the overflow exist in Top Text or Bottom Text box when more then 10000 character of text is input. So I paste the 12000 "AA..." in the Bottom Text and this happen.
This is what we wanted. The program crashes, which is the first sign that something is wrong with the application. So, lets load the program in the Ollydbg debugger to look further about the crash.
Once loaded in Ollydbg, I run the program again with same input. The program crashes again but this time ollydbg shows the given dialogue.
This shows that because of overflow eip points at 0x41414141 which is AAAA in ascii. The overflow caused eip to point at 0x41414141 either because of return address overwrite or seh handler overwrite.
Exploiting the overflow
After scrolling up the stack part in ollydbg I find out that the buffer for storing out Bottom text data starts at 0x0012db6c. Lets try first if the eip points at the location due to seh handler overwritten or not. For that I will search for expression fs:[0] in Right Click->GOTO ->Expression . This will take me to starting of TEB structure. The first four bytes in little endian format points at the first seh handler location which is 0x0012E868. After subtracting starting of buffer address from seh handler address(0x0012E868-0x0012db6c) I got the value 0xCFC. So, open hex editor like HXD and create a file in it and fill it with 12000(0x2EE0) "AAA.."s.
Now, at location 0xCFC put CCCCCCCC instead. and copy the text and paste it again in our program while running it in olly. This time you will notice the error will show that eip points to 0xCCCCCCCC. This proof that overflow is due to seh overwritten.
Our next task it to point the handler address with some useful address. We cannot point it directly to our stack because it is not allowed by OS. So, we will going to point it to "pop pop return" instruction address. For that we need to find out some address where instruction look something like this.
pop reg //where reg can be any register
pop reg
ret
It is generally easy to find these instructions in text section of program but we have a big problem here!. The text box only support ascii characters to input. That means you cannot put value between 0x00 to 0x20 and some other like 0x90(nop). So if address has these non supporting hex value then it will not going to work. By keeping this in mind lets move on with finding pop pop ret.
We can look for pop pop ret in some other loaded library(like ntdll.dll)'s code section but that will not going to work. It is because of "Safe SEH" turned on for these dll's. Safe Seh tells our os that seh handler cannot point at this dll's address. Most windows default dll's have safe seh turned on but lets check it first. For that we will going to use ollysseh plugin which will show which loaded dll has SafeSeh on/off.
Interestingly, the executable itself's image(BarcodeWiz.exe) and one dll name "MSVBVM60.dll" have safeseh off. We cannot use the address from the programs executable because it has 0x00 in the starting of address. So our only hope to find pop pop ret is MSVBVM60.dll.
After scrolling a little in .text section of MSVBVM60.dll I found the required instructions at 0x72942054. And good news is, all hex value's come under ascii character range.
So, In our payload text( opened in HXD), put that address in little endian form at 0xCFC. Now, put the break point at the any of three instructions and run the program. After copying payload file in Bottom text and pressing enter you will get to the breakpoint. Steping one/two instructions(according to where you put your BP) your eip get point into user control stack address at 0x0012E864.
0x0012E868 is the address where we put our pop pop ret pointer which we cannot replace. So to add our shellcode in stack we need to pass that 4 bytes using jmp instruction. Our jmp need to have hex values in ascii range. So we will going to use "JA 21" which is "jump above 21 bytes" with opcode " 77 21". Remaining first two bytes we will replace with "4C" which is "DEC ESP" instruction.
After running the program with payload, break at 0x12E866.
The jmp will land us at 0x12E889. Now we can put our payload here. We have enough room to put our payload but we are limited in payload due to ascii character limitation.
You can use msfvenom to generate your only alphanumeric shellcode using following command.
msfvenom -p windows/messagebox EXITFUNC=process BufferRegister=ESP -e x86/alpha_mixed -f c
But in my knowledge the success rate of this to work is very low. So, for this tutorial we will just going to use already available functions in dll's to do something interesting. While searching for all dll's loaded in memory for some good function to point our eip to, I came across MessageBeep function in USER32.dll. We can point our eip to it using jump. But first we also need to push the parameters required by MessageBeep onto the stack. For that lets look at msdn of MessageBeep.
If we just push uType value to 0xFFFFFFFF in stack then our work to push all parameters is done. "push -1" or "push 0xFFFFFFFF" have opcode of "6A FF". The address of MessageBeep is at 0x77962939, so we need to add opcode of "jmp 0x77962939". Putting all this in our payload make it look like this:
Here "E9 A6 40 83 77" is the opcode for our jmp 0x77962939. Also I have put 6A FF twice because one 6A FF is bogus push which MessageBeep expect as return address before uType parameter. After continuing the execution you will find a jump to MessageBeep which will produce a beep sound.
We have successfully exploited a buffer overflow in Windows application which have input restriction for only supporting ascii characters. Next time if you going to see such program having such restrictions you know it can be exploited using little extra work and mind.