Friday, 5 April 2013

Demystifying the Execve Shellcode (Stack Method)



We launched the SecurityTube Linux Assembly and Shellcoding Expert course recently. The course introduces the student to the basics of Assembly Language, Shellcoding, Encoders, Crypters and Polymorphism. I've decided to take up some of the course material and write posts about them. Even if you are not a student of the course, you should be able to follow these posts. Hopefully, this will be a lot of fun for both of us! :)

In this first post, I am going to take a look at probably the most popular shellcode - Execve! There are multiple ways to write shellcode but the most popular implementations use the Stack and the JMP-CALL-POP method. The subject of this post is creating Execve shellcode using the Stack method.

If you have no clue what Shellcode is, then have a look at the explanation on Wikipedia.  I will assume that you understand the basics of IA-32 assembly language and at least know what Shellcode is.

OK, let the games begin! 

Objective: To create an Execve Shellcode which can launch /bin/sh

Lab Setup I am using is Ubuntu 12.04 32-bit Desktop Edition. Most of the steps would remain the same even if you use other flavors of Linux.

Let's look at the whole process in a step-by-step way:

Step 1: Find the system call number for Execve


As you can see from the image above, Execve has system call number 11.

Step 2: We need to call Execve in our shellcode, so we would need to know the arguments it takes as input. Man pages to our rescue!



The 3 arguments must contain the following:

  • filename must point to a string containing the path of the binary we want to execute. In our case, this would be the string "/bin/sh". If you are not from the C world, "point" means the address of the string, and not the string itself.
  • argv[] is the list of arguments to the program. Most programs will use mandatory / option arguments to run e.g. telnet 192.168.1.10 The argument here is "192.168.1.10". In our case, we only want to execute "/bin/sh" without any more arguments, so the argument list is just a NULL pointer (0x00000000 address). However, there is a twist :) by convention, the first argument is the filename we want executed. So, argv[] would really be ['/bin/sh'. 0x00000000]
  • envp[] is the list of any additional environment options you want to pass to the program in key:value format. This will be NULL pointer / 0x00000000 for our purpose

 Step 3: Lets map the CPU Registers for the Execve call. The following registers will be used for the system call using INT 0x80



 This would be the mapping then. EAX would contain "11" which is the system call number for Execve as found in Step 1



 Step 4: Let the coding begin! I am using the below skeleton code for our program

 

I've only defined the TEXT section and the entry point into this executable would be _start. 

Step 5: We will now setup the Stack with all the arguments required for Execve as discussed in Step 3. Remind yourself that the stack for IA-32 grows from High Memory to Low Memory.




Step 6: Let us setup the EBX register first. EBX needs to point to "/bin/sh" in memory. Now the string would have to be '\x0' terminated. Let us setup the NULL first by pushing a 0x00000000 onto the stack. Now we cannot do a "PUSH 0x00000000" because Shellcode cannot contain NULLs as this is the most common bad character. Hence we will have to create 0x00000000 in one of the registers and PUSH the register on the stack. We will use the XOR operation to zero out EAX and then PUSH EAX on the stack:


The stack should look like this right now:


We now need to PUSH "/bin/sh" on the Stack. As the Stack grows from High Memory to Low Memory in x86 we will need to push "/bin/sh" in reverse order :) Also, it would be easier to push data which is a multiple of 4 with the least number of instructions. This is desirable as the smaller the shellcode, the greater the number of scenarios where we can use it. 

Now, "/bin/sh" is 7 bytes and we need to convert it to 8 bytes without messing up the filename. On Linux this is easy to do because "/bin/sh" invokes the same program as "//bin/sh".  Multiple "/" in succession does not cause any problems as you can see below:


Awesome! Now we need to PUSH "//bin/sh" (8 bytes) in reverse on the Stack i.e. "hs/nib//" Here is a quick way in Python to generate the value in hex:


Don't we all just LOVE Python :) Let's add the PUSH in the code now with the hex values above.



After the 2 PUSH instructions, this is how the Stack should look like:


Awesome! Now let us make EBX point to the top of the Stack! This would really mean EBX is now contains the address of "//bin/sh" in memory. This can be easily done by copying ESP into EBX



Step 7: Let us now setup EDX which if you remember should point to a NULL pointer. This can be easily achieved by a PUSH EAX (remember EAX contains 0x00000000) and copying ESP into EDX.


The Stack looks like this right now:



Step 8: The last piece of the puzzle ECX still remains! ECX needs to contain the address of [Address of //bin/sh in memory, 0x0000000] as discussed previously. Currently EBX contains the address of "//bin/sh" in memory so let's PUSH EBX on the Stack


If you notice, the top of the Stack now points to [Address of //bin/sh in memory, 0x00000000] This is exactly what we wanted! So let's write out the code to copy ESP into ECX


Step 9: All the arguments for Execve are now setup on the Stack and EBX, ECX and EDX are pointing to them. The Stack looks like this right now:


Step 10: Let us now call Execve! We setup EAX to contain "11" and invoke Interrupt 0x80


The code for Execve-Stack.nasm is available below for copying:



Now let us Assembly, Link and Test the code:



Let us look at the binary using Objdump (we could also use the .o file) The highlighted hex values are the actual IA-32 opcodes.


We need to extract all the opcodes to create our shellcode. As cumbersome as this looks, I am happy to report there is a shortcut available:


Here is the final extracted Shellcode - pretty much looks like ... any other piece of Shellcode :)


Step 11: I am going to use the following C program to test the shellcode to ensure we have not mistakenly used any hardcoded address and anything else which would disallow this shellcode from running inside another process.

Let us now compile shellcode.c and run it to test!


Fantastic! So our Execve Shellcode is working great! In the next post we will look at automating Shellcode generation for Execve using N arguments using Python. Stay tuned!


If you've never done Assembly Language / Shellcoding etc. before then please checkout my SecurityTube Linux Assembly and Shellcoding course which aims to teach the basics of assembly language on the Linux platform from a security perspective and its application to writing shellcode, encoders, decoders and crypters, among other things. The course material is over 9 hours of HD videos!

Thursday, 4 April 2013

Simulating an SSH Worm using Python



The topic of SSH Worms came up when I was speaking with a couple of students attending my workshop at Blackhat Europe in Amsterdam last month. One of the students was curious about the iPhone SSH Worm which has been around since 2009 and the technical complexity of writing a worm for academic and research purposes. 

After explaining to him how the worm worked I realized that many think "network worms" are really complex digital beasts and only the super elite blackhats can write them. In reality, nothing could be further away from the truth. The only complex part in most worms is the exploits they use for breaking in (which in most cases might be ripped from sites like exploitdb). The network propagation and replication aspects are quite simple.

I decided to create a "simple worm" demo in Python for demonstration purposes. Why Python? HLLs like Python are easy to understand even by non-programmers as they are very readable by design. 

The SSH worm in question was really using the default password "alpine" on jailbroken phones to break in and propagate. We will take a short detour and instead Bruteforce the SSH password using a word list.

So, if I were to breakup our "demo worm" functionality wise, it would do the following:

1. Scan a new IP address and if SSH is running try and bruteforce the login / password 
2. If the worm succeeds, then upload a copy of itself to the host
3. Run the copy, so it can now scan and do (1)-(3) 

Important: I am not going to give out the whole source code, rather will look at components separately. This is to prevent script kiddies from using the code as is. The video at the end of this post shows a full demo on my lab setup with a couple of victim machines. 

The above steps (1)-(3) can be broken down into just 2 functions:

1. SSHDictionaryAttack()
2. UploadAndExecute()

Now SSH is a complicated protocol and to write the low level transport encryption code will be a pain :) This is where Python is gonna be of help to us. We will be using Paramiko as our SSH Library.

Below is the code for a Dictionary based attack on SSH:

The sample username:password file would be in the following format:

A sample run of the script against a vulnerable SSH installation:


Awesome! Now lets look at once you have a valid SSH username:password, how we would go about implementing UploadAndExecute()


Lets do a quick run of the UploadAndExecute() code:


Awesome! We can see that Payload.py was upload and executed. This end up creating the directory hacked.

Now, one of the issues with Python and using 3rd Party Libraries like Paramiko is that if the worm were to run in the "Python" form then the victim's would need to have Python + Paramiko installed. This is not a very practical expectation. So what do we do? PyInstaller to the rescue!

According to their website: PyInstaller is a program that converts (packages) Python programs into stand-alone executables, under Windows, Linux, Mac OS X, Solaris and AIX. Its main advantages over similar tools are that PyInstaller works with any version of Python since 2.3, it builds smaller executables thanks to transparent compression, it is fully multi-platform, and use the OS support to load the dynamic libraries, thus ensuring full compatibility.

This is exactly what we need! Lets convert both the above scripts to stand-alone executables using Pyinstaller as below:


Fantastic! Remember to use the "--onefile" option!  Now let me bring together the above components into one script and call it SSH-Worm-Demo.py! Sorry I cannot share the source code for fear of abuse, but if you've understood the above code samples, I am sure you understand how the code works. Basically SSH-Worm-Demo.py does the following:

  • Figures out the subnet IP addresses and scans for SSH services
  • Launched the Dictionary Attack on an SSH Service
  • Uploads and Executes a copy on the victim if it manages to break in
  • All files are created in the /tmp/ folder by the worm
  • It calls "wall" with the word "hacked" so that it can be displayed on the terminal
  • I've used Pyinstaller to convert SSH-Worm-Demo.py into a single executable file ssh-worm

I've setup 4 Ubuntu 12.04 Server machines as victims. Before I run the worm, this is how the /tmp looks like on each of them:


I run the worm from Victim-1 and very soon you see  the "Hacked" messages appear on all terminals:


As this is a simple demo code, I am not checking if the worm has already infected the machine and hence we are having duplicate infections :) Below is a screenshot of the /tmp as the infection spreads:


As you can see, every new infection creates a new executable file (the green ones with random names) and *.wall file.

Below is a short video demo of the same:





Awesome! Worm behavior simulated with Python!

If you are interested in learning how to use Python for Pentesting then please have a look at our SecurityTube Python Scripting Expert course. This course is ideal for penetration testers, security enthusiasts and network administrators who want to learn to automate tasks or go beyond just using ready made tools. We will be covering topics in system security, network security, attacking web applications and services, exploitation techniques, malware and binary analysis and task automation.We have students from 73+ countries taking this course already!




Wednesday, 3 April 2013

Bypassing Jailbroken Checks in iOS Applications using GDB and Cycript



I've been teaching iOS Application Security and Auditing to pentesters and developers (secure programming guidelines) online / real world and one of the questions which always comes up is can Anti-Piracy measures work if implemented in the application? Pentesters want to know if they could run into problems with applications implementing runtime protections. Developers on the other hand, want to know if they can sleep well if they implement such protections.

The short answer is NO, if your code runs on a platform controlled by the attacker, and if he is skilled enough, he would eventually figure out how to subvert your protection. This is especially true for a Jailbroken device where the attacker can pretty much run anything. 

I can already see pentesters smiling :) If you know how to do runtime analysis using Cycript and GDB, then you should be able to subvert most protections. However, as this is significantly different from other application pentests (web and network) and involves a component of reverse engineering an application on the ARM platform, this might get interesting and challenging! 

This blog post is the first in the series I am planning to talk about the common techniques used by developers today to check for jailbreaking and how an attacker could subvert them.

In order to try things out and we need a sample application! :) I've created a simple AntiPiracyDemo Application for iOS which I use for my online iOS course. You can download the IPA here. Please note that this is a self-signed application and would require a Jailbroken device (iPhone / iPad) to run.

You can install the application using installipa as shown below:







 The application has been tested on iOS 5.1.1 and 6.1.2.  Once you run the application, you can confronted with a simple screen to check for Jailbroken state:







Clicking on the button, confirms this application is running on a Jailbroken phone. The developer of a real world application can now exit or send a report (privacy violation? :) ) back to his server to notify.







Objective: To bypass the is Jailbroken check implemented by the iOS Application

 Step 1: Find the application PID and the directory in which it is installed. This is easy to do using "ps" along with a "grep" for the application name



Step 2: Go to the Application directory and locate the actually application binary


Step 3: Native iOS applications are written in Objective-C which is a dynamically typed language. This requires that all the class information be available at runtime and hence is embedded into the binary. We can extract this class information using a tool called class-dump-z as show below:

Step 4: View the class information file - there is a ton of information in there! :) 


Step 5: We need to find the rootViewController for the current window. This can be done using a tool called Cycript, which uses Mobile Substrate to hook into any running application. We can find the current rootViewController as below:



Step 6: Lets go back to the out of class-dump-z in Step 4 and find the "@interface" section for AntiPiracyViewController


Step 7: We see a "checkPiracy" method and more interestingly - we see a method called "isJailbroken" which returns a BOOL and takes no inputs which probably means this checks for a jailbroken state.



We can use 2 different techniques to  bypass this protection  -- 

1. Runtime Modification using GDB 
2. Method Swizzling using Cycript


Let's take up Runtime Modification using GDB first

Step 1: Attach GDB to AntiPiracyDemo using the PID


Step 2: Set a Breakpoint for the isJailbroken 


Step 3: Continue running the application and then click on the "Am I Pirated" button to see if we hit the breakpoint



Step 4: Disassemble! :) Be Prepared for some unfamiliar looking symbols if ARM Assembly is not your thing :)


Step 5: iOS devices have an ARM based processor and what you are seeing is ARM Assembly. If you are from the x86 world then there is only one thing you need to keep in mind when working with ARM assembly - the arguments are passed via the registers R0, R1, R2, R3. More than 4 arguments are passed on the stack.  Here is the ABI document if you are interested. 


 Step 6: In the disassembly in Step 4, you see a lot of "blx    0x98fe4 <dyld_stub_objc_msgSend>"  BLX is "Branch with Link" which basically ends up calling objc_msgSend which has the following definition:


 The above is the from Apple Developer site. Objc_msgSend is really the "carrier" of all messages inside an iOS application. Using the ABI we can conclude that:

  1. theReceiver would be pointed to by R0
  2. theSelector would be pointed to by R1
  3. First argument pointed to by R2

Step 7: We could set a breakpoint for objc_msgSend but I would prefer to add breakpoints in all locations its called to better illustrate the concept. So, let's set the breakpoints:

Step 8: Let's continue running the application and let's dump R0/R1 when we hit the Breakpoint 2. This will help us understand the receiver of the message and its respective selector


NSSString alloc is not interesting, Let's repeat the same for other breakpoints. Below is the output when we hit Breakpoints 4 and 5.


Breakpoint 4 tells us that the application is using NSFileManager and Breakpoint 5 tells us it is checking for "FileExistsAtPath:" for "/private/var/lib/apt" Very interesting! 

APT is probably is one of the first binaries to be installed on a Jailbroken phone to manage packages from Cydia. Looks like the developer is checking for the presence of this binary. 
Step 9: So where do we go from here? The return value is stored in R0 and if you check the documentation of NSFileManager FileExistsAtPath it returns a BOOL. This means "0" will be returned in case the device is NOT Jailbroken and "1" will be returned if it IS Jailbroken. 

In our case, as our iPhone is jailbroken, it will return "1". We can verify this by setting a breakpoint in the next line of code and checking the value of R0 as below:



Step 10: The easiest way to subvert this mechanism would be to change the value of R0 from "1" to "0" so that it indicates to the application that the APT does not exists and hence the device is not Jailbroken. We can do this very easily:

Step 11: If we check the Application now - it happily tells us that "This iPhone is NOT Jailbroken"


Of course, we have not patched the check in the binary so you would need do this every time :) I will take up Application Patching in another blog post. 




Now let us look at the other technique - Method Swizzling using Cycript

Step 1: Attack to the application using Cycript



Step 2: Method Swizzling allows you to change the mapping for a given method to your own implementation of it.  To get the list of messages available we use isa.messages


The above command should give you a ton of output! You can clearly see isJailbroken is there in it as highlighted. What is really isa.messages?

If you look at the Objective-C runtime implementation, then isa is really a pointer to the class structure itself.

Implementation File:

http://www.opensource.apple.com/source/objc4/objc4-532/runtime/runtime.h

isa is never exposed to the programmer directly but with Cycript we are able to access it. Quoting from Apple's website:

If you’re a procedural programmer new to object-oriented concepts, it might help at first to think of an object as essentially a structure with functions associated with it. This notion is not too far off the reality, particularly in terms of runtime implementation.

Every Objective-C object hides a data structure whose first member—or instance variable—is the isa pointer. (Most remaining members are defined by the object’s class and superclasses.) The isa pointer, as the name suggests, points to the object’s class, which is an object in its own right (see Figure 2-1) and is compiled from the class definition. The class object maintains a dispatch table consisting essentially of pointers to the methods it implements; it also holds a pointer to its superclass, which has its own dispatch table and superclass pointer. Through this chain of references, an object has access to the method implementations of its class and all its superclasses (as well as all inherited public and protected instance variables). The isa pointer is critical to the message-dispatch mechanism and to the dynamism of Cocoa objects.

Please read the rest here: https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CocoaFundamentals/CocoaObjects/CocoaObjects.html

The last line of the above excerpt summarizes the importance of isa in message dispatching. Here is more information on it:

The key to messaging lies in the structures that the compiler builds for each class and object. Every class structure includes these two essential elements:

  • A pointer to the superclass.
  • A class dispatch table. This table has entries that associate method selectors with the class-specific addresses of the methods they identify.

Full Details here: https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtHowMessagingWorks.html

Step 3: It's OK if the above does not make any sense :) but it's good to know what is really happening in the background. Now let's change the implementation of isJailbroken with Cycript


Step 4: Now when you try Clicking on "Am I Pirated?" you will always get a "NO" :) W00t :)





Hope you enjoyed this post. I will creating more posts on Bypassing more checks like Binary checks, Bundle and Hash checks etc. in coming posts. Stay tuned!

                           

If you are interested in learning how to methodically understand many of the above concepts and test iOS applications with a blackbox approach, then please have a look at my SecurityTube iOS Security Expert (SISE) is an online course and certification which focuses on the iOS platform and application security. This course is ideal for pentesters, researchers and the casual iOS enthusiast who would like to dive deep and understand how to analyze and systematically audit applications on this platform using a variety of bleeding edge tools and techniques.









Tuesday, 2 April 2013

Converting Airdecap-NG into a Word List based WEP Cracker



We all know that WEP can be cracked, but can you crack a WEP network with only one Data packet?

Traditionally WEP Cracking has always involved making the victim network generate a ton of WEP encrypted data packets. Then one uses tools like Aircrack-NG to crack the WEP key using various cryptographic flaws in WEP. The ballpark number of packets is roughly between 30k-120k data packets. I'd also like to take this opportunity to say how fantastic Aircrack-NG is and how my friend Mister_X, it's creator, is without a shadow of a doubt one of the most talented programmers / security researcher I have ever had the privilege of knowing.

Now back to my blog post :) ----  However, what if you only have one WEP Data packet as in this trace file? Here is a quick look at the file with Wireshark:


To begin with there is no cryptographic attack which can crack WEP with just one Data packet. The only way would be to launch a dictionary attack against the Data packet. If we successfully decrypt it with a given key, then it is the right one. This really the same way we crack WPA/WPA2-PSK right now.

The problem we run into is that most WEP cracking tools do not support a dictionary based attack on WEP. There is a tool in the Aircrack-NG suite - Airdecap-NG which can decrypt WEP packets if we know the key, but it cannot take a dictionary as input. Below is a quick dump of the it's options:


The option that is interesting to me is the "-w" one. So with this, let me define our objective.

Objective: To create a Python script which can use Airdecap-NG along with a Word List and try to Crack WEP with just a single Data packet

Let's analyze the solution in steps:


Step 1: If we called Airdecap-NG from within our script, how would we know it has managed to find the right WEP key? To solve this, let's look at the output of Airdecap-NG when it FAILS to decrypt a packet using the supplied WEP key


We clearly see that Line No 5 of the output "Number of decrypted WEP packets" is "0".

Let's now see how it looks like when the decryption SUCCEEDS if we have the right WEP key:


Fantastic! Line no 5 not has "1" in the rightmost column because we managed to decrypt the packet.


Step 2: So we need to write a Python script which does the following:

  1. Takes a Word List and the Pcap file containing the WEP data packet as input
  2. It uses all the words of length 5 or 13 characters as the WEP key is really 40/104bits in length
  3. For each key, call airdecap-ng and check the output 
  4. If the output does not contain "1" in Line no 5, then continue with (3)
  5. If the output contains "1" in Line no 5, then stop and print the WEP key used. This is the correct key
I wish I had the time to make a flow chart for the above :)


Step 3: Let's code this up:





Step 4: Let's run this against the pcap file and use the default dictionary in Backtrack.


Step 5: Now the Python + Airdecap-NG are doing a lot of work for us. Let's appreciate that a bit by looking at the output while it is still running :)


Eventually, if the WEP key is in the wordlist, we will find it :)


The WEP key used by the network was "tudes" as we can see from the last line of the output.

Step 6: You can also see the decrypted packet using Wireshark



Awesome! Hopefully this has been an interesting illustration of how you can use Python for automating tasks using existing tools which are available, rather than wait for a new tool or a feature in an existing one.

If you enjoyed, leave a comment behind or please Tweet / Share this post. Thanks!

If you are interested in learning how to use Python for Pentesting then please have a look at our SecurityTube Python Scripting Expert course. This course is ideal for penetration testers, security enthusiasts and network administrators who want to learn to automate tasks or go beyond just using ready made tools. We will be covering topics in system security, network security, attacking web applications and services, exploitation techniques, malware and binary analysis and task automation.We have students from 73+ countries taking this course already!




Monday, 1 April 2013

Wi-Fi SSID Sniffer in 11 Lines of Python using Raw Sockets



I covered writing a Wi-Fi SSID Sniffer using Scapy in just 10 lines in a previous post.  Interestingly, a lot of people (mostly developers) want to know how your code would look like if you did not use scapy?

Here was the old scapy version I posted today:



Here is a raw socket version of the same code :)




The above jumps over the Radiotap header, get the MAC address in address field 2 and then gets the first Tagged TLV (typically the SSID) from the Beacon header. This is definitely not the most production ready code :) and needs a lot of work (need to iterate through TLVs in case SSID is not the first one etc. ) but seems to work quite well -- below is a sample output.

I'll probably do a more detailed writeup explaining the code later in the week with some more checks to make it reliable. I think its still possible to accomplish writing a SSID sniffer in under 25 lines with no 3rd party libs being used. We'll see - Good Night! :)


If you are interested in learning how to use Python for Pentesting then please have a look at our SecurityTube Python Scripting Expert course. This course is ideal for penetration testers, security enthusiasts and network administrators who want to learn to automate tasks or go beyond just using ready made tools. We will be covering topics in system security, network security, attacking web applications and services, exploitation techniques, malware and binary analysis and task automation.We have students from 73+ countries taking this course already!