티스토리 뷰
Socketpair
일반적으로 socket() 함수를 사용하면 인자로 준 특정 프로토콜에 대해서 1개의 소켓만을 생성한다. socketpair를 이용하면 한 번에 서로가 연결된 소켓 쌍을 생성하는게 가능해진다. 흔히 AF_UNIX를 사용하여 로컬 내부에서 도메인 소켓을 사용하고자 할 때, 외부 네트워크로부터 데이터를 받아 도메인 소켓으로 특정 프로그램에 내용을 전달하는 방식으로 사용한다.
1 2 3 4 5 6 7 8 9 | int sock; int sock_pair[2]; int result; // generally sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); // socketpair result = socketpair(AF_INET, SOCK_STREAM, IPPROTO_TCP, &sock_pair); | cs |
sendmsg, recvmsg
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | int fd; // = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); char buf[MAX_BUF]; struct msghdr msg; // basic msg header struct iovec iov; // i/o vercor (about buffer information) cmsg_fd cmsg; // control message // register buffer iov.iov_base = buf; iov.iov_len = MAX_BUF; // configure msg msg.msg_name = NULL; // optional address (= sockaddr_in) msg.msg_namelen = 0; // address size msg.msg_iov = &iov; // iov that registered buffer msg.msg_control = &cmsg; msg.msg_controllen = sizeof(cmsg); msg.msg_flags = 0; // configure control msg struct cmsghdr* cptr(CMSG_FIRSTHDR(&msg)); cptr->cmsg_len = CMSG_LEN(sizeof(int)); cptr->cmsg_level = SOL_SOCKET; cptr->cmsg_type = SCM_RIGHTS; memcpy(CMSG_DATA(cptr), &fd, sizeof(int)); if(sendmsg(sockfd, &msg, 0) < 0) { perror("[-] Failed sendmsg()"); exit(-1); } | cs |
msghdr, iovec 구조체
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | /* * [XSI] Message header for recvmsg and sendmsg calls. * Used value-result for recvmsg, value only for sendmsg. */ struct msghdr { void *msg_name; /* [XSI] optional address */ socklen_t msg_namelen; /* [XSI] size of address */ struct iovec *msg_iov; /* [XSI] scatter/gather array */ int msg_iovlen; /* [XSI] # elements in msg_iov */ void *msg_control; /* [XSI] ancillary data, see below */ socklen_t msg_controllen; /* [XSI] ancillary data buffer len */ int msg_flags; /* [XSI] flags on received message */ }; /* Define to have the same layout as a WSABUF */ #ifndef STRUCT_IOVEC_DEFINED #define STRUCT_IOVEC_DEFINED 1 struct iovec { long iov_len; char *iov_base; }; #endif #else struct iovec; /* Defined in OS headers */ #endif /* * Header for ancillary data objects in msg_control buffer. * Used for additional information with/about a datagram * not expressible by flags. The format is a sequence * of message elements headed by cmsghdr structures. */ struct cmsghdr { socklen_t cmsg_len; /* [XSI] data byte count, including hdr */ int cmsg_level; /* [XSI] originating protocol */ int cmsg_type; /* [XSI] protocol-specific type */ /* followed by unsigned char cmsg_data[]; */ }; | cs |
리버싱할 때 분석 방법
우선 리버싱을 할 때, 입출력이 되는 부분인 sendmsg와 recvmsg 함수를 찾는다. 해당 함수는 총 3개의 인자를 가지며, 1번째 인자는 socket, 2번째 인자는 struct msghdr인 msg의 주소, 3번째 인자는 flags이다. 현재 중요한건 buffer이기 때문에 msg의 주소를 확인하고 struct msghdr의 구조체에 내용을 따라 값 부분을 확인하고 정의하면 된다. 다음은 IDA로 분석했을 때, 정의된 모습이다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | /* C code that is converted from Assembly code var_38 = unk_5B3944; var_34 = 0x5DC; var_30 = 0; var_2C = 0; var_28 = var_38; var_24 = 1; var_20 = dword_5B3844; var_1C = 0x100; var_18 = 0; recvmsg(sock, &var_30, 0); */ // var_38 = struct iovec var_38.iov_base = unk_5B3944; var_34.iov_len = 0x5DC; // var_30 = struct msghdr var_30.msg_name = NULL; var_30.msg_name_len = 0; var_30.msg_iov = &var_38; var_30.msg_iovlen = 1; var_30.msg_control = dword_5B3844; var_30.msg_controllen = 0x100; var_30.msg_flags = 0; | cs |
msg의 주소를 확인하면 msg의 주소 + 8의 위치에서 iov의 주소를 얻는게 가능하다. iov의 주소를 얻으면 내부에 저장된 buffer의 주소와 buffer의 크기까지 획득할 수 있다.
참고
- cmsghdr 관련 : http://pracon.tistory.com/135
'Programming > C' 카테고리의 다른 글
[Win API] CryptProtectData example (0) | 2018.08.06 |
---|---|
OLE read, write API (0) | 2018.07.27 |
[Windows] Makefile, batch 파일 예제 코드 저장본 (0) | 2018.04.03 |
Windows cl.exe option (0) | 2018.03.21 |
SSL Programming Tutorial (2) | 2018.03.18 |
댓글