require 'rex/text' require 'rex/exploitation/obfuscatejs' require 'msf/core/auxiliary' module Rex module Exploitation # # Provides several javascript functions for determining the OS and browser versions of a client. # # getVersion(): returns an object with the following properties # os_name - OS name, one of the Msf::Auxiliary::Report::OperatingSystems constants # os_flavor - OS flavor as a string (e.g.: "XP", "2000") # os_sp - OS service pack (e.g.: "SP2", will be empty on non-Windows) # os_lang - OS language (e.g.: "en-us") # ua_name - Client name, one of the Msf::Auxiliary::Report::HttpClients constants # ua_version - Client version as a string (e.g.: "3.5.1", "6.0;SP2") # arch - Architecture, one of the ARCH_* constants # # The following functions work on the version returned in obj.ua_version # # ua_ver_cmp(a, b): returns -1, 0, or 1 based on whether a < b, a == b, or a > b respectively # ua_ver_lt(a, b): returns true if a < b # ua_ver_gt(a, b): returns true if a > b # ua_ver_eq(a, b): returns true if a == b # class JavascriptOSDetect < ObfuscateJS def initialize(custom_js = '', opts = {}) clients = ::Msf::Auxiliary::Report::HttpClients oses = ::Msf::Auxiliary::Report::OperatingSystems @js = custom_js @js = <"); switch (version){ case "514615": os_flavor = "2000"; os_sp = "SP0"; break; case "515907": os_flavor = "2000"; os_sp = "SP3"; //or SP2: oCC.getComponentVersion('{22d6f312-b0f6-11d0-94ab-0080c74c7e95}', 'componentid') => 6,4,9,1109 break; case "518513": os_flavor = "2000"; os_sp = "SP4"; break; case "566626": // IE 6.0.2600.0000, XP SP0 English // IE 6.0.2800.1106, XP SP1 English ua_version = "6.0"; os_flavor = "XP"; os_sp = "SP0"; break; case "568515": // IE 6.0.3790.0, 2003 Standard SP0 English ua_version = "6.0"; os_flavor = "2003"; os_sp = "SP0"; break; case "568820": // IE 6.0.2900.2180, xp sp2 english os_flavor = "XP"; os_sp = "SP2"; break; case "568827": os_flavor = "2003"; os_sp = "SP1"; break; case "568831": //XP SP2 -OR- 2K SP4 if (os_flavor == "2000"){ os_sp = "SP4"; } else{ os_flavor = "XP"; os_sp = "SP2"; } break; case "568832": os_flavor = "2003"; os_sp = "SP2"; break; case "575730": // IE 7.0.5730.13, Server 2003 Standard SP2 English // IE 7.0.5730.13, Server 2003 Standard SP1 English // IE 7.0.5730.13, XP Professional SP2 English // Rely on the user agent matching above to determine the OS. // This will incorrectly identify 2k3 SP1 as SP2 ua_version = "7.0"; os_sp = "SP2"; break; case "5718066": // IE 7.0.5730.13, XP Professional SP3 English ua_version = "7.0"; os_flavor = "XP"; os_sp = "SP3"; break; case "5818702": // IE 8.0.6001.18702, XP Professional SP3 English ua_version = "8.0"; os_flavor = "XP"; os_sp = "SP3"; break; case "580": // IE 8.0.7100.0, Windows 7 English // IE 8.0.7100.0, Windows 7 64-bit English ua_version = "8.0"; os_flavor = "7"; os_sp = "SP0"; break; //default: // document.writeln(version); // break; } if (!ua_version) { if (document.documentElement && (typeof document.documentElement.style.maxHeight)!="undefined") { // IE8 detection straight from IEBlog. Thank you Microsoft. try { ua_version = "8.0"; document.documentElement.style.display = "table-cell"; } catch(e) { // This executes in IE7, // but not IE8, regardless of mode ua_version = "7.0"; } } else if (document.compatMode) { ua_version = "6.0"; } else if (window.createPopup) { ua_version = "5.5"; } else if (window.attachEvent) { ua_version = "5.0"; } else { ua_version = "4.0"; } switch (navigator.appMinorVersion){ case ";SP2;": ua_version += ";SP2"; break; } } } //-- // Flavor //-- if (navigator.oscpu) { // Then this is Gecko and we can do it without the useragent version = navigator.oscpu.toLowerCase(); } else if (!ua_is_lying) { version = useragent.toLowerCase(); } else { // All we have left is the useragent and we know it's lying, so don't bother version = " "; } if (!os_name || 0 == os_name.length) { if (version.indexOf("windows") != -1) { os_name = "#{oses::WINDOWS}"; } else if (version.indexOf("mac") != -1) { os_name = "#{oses::MAC_OSX}"; } else if (version.indexOf("linux") != -1) { os_name = "#{oses::LINUX}"; } } if (os_name == "#{oses::WINDOWS}" && (!os_flavor || 0 == os_flavor.length)) { if (version.indexOf("windows 95") != -1) { os_flavor = "95"; } else if (version.indexOf("windows nt 4") != -1) { os_flavor = "NT"; } else if (version.indexOf("win 9x 4.9") != -1) { os_flavor = "ME"; } else if (version.indexOf("windows 98") != -1) { os_flavor = "98"; } else if (version.indexOf("windows nt 5.0") != -1) { os_flavor = "2000"; } else if (version.indexOf("windows nt 5.1") != -1) { os_flavor = "XP"; } else if (version.indexOf("windows nt 5.2") != -1) { os_flavor = "2003"; } else if (version.indexOf("windows nt 6.0") != -1) { os_flavor = "Vista"; } else if (version.indexOf("windows nt 6.1") != -1) { os_flavor = "7"; } } if (os_name == "#{oses::LINUX}" && (!os_flavor || 0 == os_flavor.length)) { if (version.indexOf("gentoo") != -1) { os_flavor = "Gentoo"; } else if (version.indexOf("ubuntu") != -1) { os_flavor = "Ubuntu"; } else if (version.indexOf("debian") != -1) { os_flavor = "Debian"; } else if (version.indexOf("rhel") != -1) { os_flavor = "RHEL"; } else if (version.indexOf("red hat") != -1){ os_flavor = "RHEL"; } else if (version.indexOf("centos") != -1) { os_flavor = "CentOS"; } } //-- // Language //-- if (navigator.systemLanguage) { // ie os_lang = navigator.systemLanguage; } else if (navigator.language) { // gecko derivatives, safari, opera os_lang = navigator.language; } else { // some other browser and we don't know how to get the language, so // just guess english os_lang = "en"; } //-- // Architecture //-- if (!arch || 0 == arch.length) { version = navigator.platform; //document.write(version + "\\n"); // IE 8 does a bit of wacky user-agent switching for "Compatibility View"; // 64-bit client on Windows 7, 64-bit: // Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Win64; x64; Trident/4.0) // 32-bit client on Windows 7, 64-bit: // Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0) // 32-bit client on Vista, 32-bit, "Compatibility View": // Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Trident/4.0) // // Report 32-bit client on 64-bit OS as being 32 because exploits will // need to know the bittedness of the process, not the OS. if ( ("Win32" == version) || (version.match(/i.86/)) ) { arch = "#{ARCH_X86}"; } else if (-1 != version.indexOf('x64') || (-1 != version.indexOf('x86_64'))) { arch = "#{ARCH_X86_64}"; } else if (-1 != version.indexOf('PPC')) { arch = "#{ARCH_PPC}"; } } return { os_name:os_name, os_flavor:os_flavor, os_sp:os_sp, os_lang:os_lang, arch:arch, ua_name:ua_name, ua_version:ua_version }; } // function getVersion function searchVersion(needle, haystack) { var index = haystack.indexOf(needle); var found_version; if (index == -1) { return; } found_version = haystack.substring(index+needle.length+1); // Strip off any junk at the end such as a CLR declaration found_version = found_version.substring(0,found_version.indexOf(' ')); return found_version; } /* * Return -1 if a < b, 0 if a == b, 1 if a > b */ function ua_ver_cmp(ver_a, ver_b) { // shortcut the easy case if (ver_a == ver_b) { return 0; } a = ver_a.split("."); b = ver_b.split("."); for (i = 0; i < Math.max(a.length, b.length); i++) { // 3.0 == 3 if (!b[i]) { b[i] = "0"; } if (!a[i]) { a[i] = "0"; } if (a[i] == b[i]) { continue; } a_int = parseInt(a[i]); b_int = parseInt(b[i]); a_rest = a[i].substr(a_int.toString().length); b_rest = b[i].substr(b_int.toString().length); if (a_int < b_int) { return -1; } else if (a_int > b_int) { return 1; } else { // == // Then we need to deal with the stuff after the ints, e.g.: // "b4pre" if (a_rest == "b" && b_rest.length == 0) { return -1; } if (b_rest == "b" && a_rest.length == 0) { return 1; } // Just give up and try a lexicographical comparison if (a_rest < b_rest) { return -1; } else if (a_rest > b_rest) { return 1; } } } // If we get here, they must be equal return 0; } function ua_ver_lt(a, b) { if (-1 == ua_ver_cmp(a,b)) { return true; } return false; } function ua_ver_gt(a, b) { if (1 == ua_ver_cmp(a,b)) { return true; } return false; } function ua_ver_eq(a, b) { if (0 == ua_ver_cmp(a,b)) { return true; } return false; } ENDJS super @js update_opts(opts) if (opts) update_opts({'Symbols' => { 'Variables' => [ 'os_name', 'os_flavor', 'os_sp', 'os_lang', 'arch', 'ua_name', 'ua_version', 'found_version', 'needle', 'haystack', ], 'Methods' => [ 'getVersion', 'searchVersion' ] } }) #self.obfuscate return @js end end end end