After many (many) months of procrastination, I’ve finally put the first couple of pieces together for an idea I’ve had going round in my head since the beginning of the year. What finally made me get things rolling ? well, it’s a number of things really. I managed to sit and chat with Carlos “Darkoperator” Perez before his talk at Defcon, and his enthusiasm for Metasploit and what the project was trying to achieve really made me want to be a bigger part of that. Still, I’m rambling and not getting to the point. So what is this idea I had, and why is it important enough to write about it.
To most people who read my blog, this isn’t going to be something that effects your everyday life, but you have to remember that not everybody using Metasploit comes from the US/UK. There’s a whole world of people out their using Metasploit on machines that are installed in different languages. Most people wouldn’t think twice about it. After all it’s just the system language, why would that have an effect on anything we want to exploit. Well here’s the problem. Different language versions of Windows have a range of differences that might break, or limit your use of Metasploit. That’s bad right ? Nobody wants to have to say they could exploit an unpatched system just because it’s running an Italian version of Windows 2003.
Coming from the UK, and speaking English, I never considered this could be a problem. That is, until I started preparing for a class on Metasploit last year. None of the testing I was doing on my Windows 2003 VM was working, even though I’d not patched it against MS08-067, I couldn’t exploit the box. It was just crashing, every time. Sure 1 or 2 crashes can happen, but every time without fail. Something was wrong. Why was this happening ? Because the memory offsets are different between the language versions of Windows. It’s not only that… when looking through the payloads the adduser.rb payload defaults to a hard-coded net localgroup command, which although it’ll work on 75% of systems (lots of languages use the Administrators group after all) there were specific languages that would just fail (German being one of them).
After looking a little further I came up with a few other scripts (mostly meterpreter POST exploitation scripts) that used hard-coded group names, service names, and screen scraping to do their magic (and yes, some of them are real magic). They served the purpose and they did the job great, but not for me.
So where to start. First off I took at at the MS08-067 exploit. I wanted to get a feel for how the exploits were written in Ruby (a new language for me) and wanted to see if I could replicate the exploit and get it working on a German version of Windows 2003 (language support for Windows XP is much better owing to the widespread use of it, and ease of finding testers). After some testing with msfpscan I found some alternative memory addresses that worked for the German version of 2003 sp1/sp2 (without NX enabled). After playing about a little more I even managed to find addresses that worked for both the English and the German versions. That however was the easy part. Finding the NO-NX memory addresses was pretty simple (child’s play for most probably). The challenge of the NX exploits is something I need to work more on. My Fu is weak in that area.
This last weekend I finally had some time to sit down and concentrate on understanding the way that the adduser.rb payload works. Once you look at the code things are pretty straight forward. I’m surprised more people don’t read the code, as it’s pretty simple once you get started. I guess some people are scared of coding. After some thoughts on how to proceed, I came to the realization that whatever I did should be language neutral, after all whats the point in me adding in 5 language options into the payload and letting the user pick the one they want. That’s not much of a move towards being language neutral is it. I also realized that the command for finding the language (and the name of the local Administrators group) needs to run on the client-side. After all, it needs to work with msfpayload and that runs a command completely on the client. For maximum effect it needs to adapt to the language used on the fly.
After spending some time mulling over the possible solutions, I zoned in on the use of WMIC to output the information. I know this is going to cut-off Windows NT/2000 systems, but this was the most elegant solution available. With a little help from trust Google (and Ed Skoudis) and a lot of trial and error, I managed to output the information I needed in a format that was usable based on the common local Administrators group SID number. The good thing about this solution is that it will not only be language neutral, but will also allow me to still add a user to the Administrators group even if the crafty Admin has renamed it to something else. After all the SID remains the same (S-1-5-32-544). The wmic command for people who want to play is .:
wmic group where sid=”S-1-5-32-544″ get name
The adduser_wmic.rb payload is still in testing, but for those that want to take a look, you can grab a copy here. Just let me know if you encounter any problems. I know there are currently some issues with the windows/adduser/bind_tcp payload, but once these are fixed in the SVN, I’ll resume testing with the wmic version.
Hopefully I’ll be working more in this project in the coming months (maybe even talk about it briefly at a conference). Let me know if you want to help with testing, as I could always use testers with access to Windows systems of different languages.
you should probably take a look at canvas and see how they are tackling the problem. As i dont have any real foreign language targets i havent really played with it but they tout it as being able to address some of the foreign language issues.
Good to know, thanks. I’m actually due to have a conference call with a few guys from Core about the same issues sometime this week, so I guess CANVAS are next on the list. I’ve got a copy from last year sometime so I can take a look at the code and see what they were doing at that point in time.
Thanks again for the pointer…
Nice work! I believe CANVAS handles it in couple ways, mostly they just return to codepage addresses that don’t change as often, but I haven’t had good luck with the same technique. Immunity also developed the language fingerprinting technique that I implemented for MS08-067. The issue was adduser.rb and using “net user” vs “wmic” is that only newer versions of windows have wmic.exe — it wouldn’t work on older 2000 machines for example. The adduser payload is just a slim wrapper around exec, you can implement the same thing by using the “exec” payload and just setting CMD to “wmic something something” instead of creating a new payload module (or better yet, use meterp and script it out).
The lack of support for systems before Windows 2000 is an issue. I’m looking to work a little more on the script to make it an option of adduser.rb instead of a seperate script altogether.
I can see the point about just inserting it into a EXEC payload, but getting the syntax just right to function but not break the payload takes a little bit or trial and error (just ask my girlfriend). I’ll work a little more on it and see if it’s something you want to add to SVN. If not I’ll leave it here for those interested (and personal use of course).