If you restart the surgemail service, reattach the debugger to the process, and rerun the module, you should see the crash that fuzzing found in your debugger. If you’re using the Immunity Debugger, you should be able to see the contents of the SEH chain by selecting View▸SEH chain. Right-click the value, which should be 41414141, and select Follow address in stack to display the stack contents leading to the SEH overwrite in the lower-right pane shown in Figure 14-2.
Now that you know that you can control the SEH chain on the vulnerable surgemail process with an overly long buffer, it’s time to determine the exact length required to overwrite it on the target. As you will recall from our discussions of stand-alone exploit development, before you can use a return address, you first need to find out where, exactly, the overwrite occurs.
We can modify our fuzzer code to create a nonrepeating, random string of characters of a specific length, as shown next:
print_status("Generating fuzzed data...")
fuzzed = Rex::Text.pattern_create
(11000)
print_status("Sending fuzzed data, buffer length = %d" % fuzzed.length)
req = '0002 LIST () "/' + fuzzed + '" "PWNED"' + "\r\n"
In this listing, we use Rex::Text.pattern_create
to generate the nonrepeating random string of characters with our fuzzer. Rerunning the fuzzer module now shows that SEH was overwritten on the target with 684E3368, as shown in Figure 14-3.
With the SEH overwritten with our random set of characters, we can use pattern_offset.rb in /opt/metasploit3/msf3/tools/ to determine exactly where the overwrite occurs by passing the characters of interest (684E3368) followed by the length of the string that was sent to the target (11000), as shown here:
root@bt:˜/.msf3/modules/auxiliary/fuzzers#/opt/metasploit3/msf3/tools/pattern_offset.rb
684E3368 11000
10360
The value 10360 means that the four bytes that overwrite SEH are 10361, 10362, 10363, and 10364. We can now change the fuzzer code one last time to verify our findings:
print_status("Generating fuzzed data...") fuzzed = "\x41" *10360
fuzzed << "\x42" *4
fuzzed << "\x43" *636
print_status("Sending fuzzed data, buffer length = %d" % fuzzed.length)
As shown, the fuzzer will build the malicious request beginning with 10,360 As (hexadecimal 41), followed by four Bs (hexadecimal 42) to overwrite the SEH, and then 636 Cs (hexadecimal 43) as filler to keep the string length constant at 11,000 bytes.
Running the fuzzer against the target again shows that the entire SEH chain is under your complete control, as shown in Figure 14-4.