[개발환경]
Windows 10 64bit
[개발도구]
MS Visual Studio 2022(v143, SDK 10.0)
Release x86
Bind Socket
bind() 함수는 소켓을 특정 주소 및 포트에 바인딩하는데 사용할 수 있다.
connect()함수와 유사하게 sockaddr_in 구조체가 필요하다.
int __cdecl main(int argc, char** argv)
{
WSADATA wsa;
SOCKET s;
struct sockaddr_in server;
const char* message;
char server_reply[5000];
int recv_size;
//Intialising Winsock
wprintf(L"\\nInitialising Winsock...\\n");
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) {
wprintf(L"Failed. Error code : %d", WSAGetLastError());
return 1;
}
wprintf(L"Initialised.\\n");
//Create Socket
if ((s = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {
wprintf(L"Could not create socket : %d", WSAGetLastError());
}
wprintf(L"Socket Created\\n");
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(8888);
if (bind(s, (struct sockaddr*)&server, sizeof(server)) == SOCKET_ERROR) {
wprintf(L"Bind failed with error code : %d ", WSAGetLastError());
}
puts("Bind done");
closesocket(s);
WSACleanup();
return 0;
}
Listen
소켓을 포트에 바인딩한 후 다음 작업은 연결을 수신하는 것이다. 이를 위해 소켓을 리스닝 모드로 설정한다.
//Listen
listen(s , 3);
Accept connection
int __cdecl main(int argc, char** argv)
{
WSADATA wsa;
SOCKET s, new_socket;
struct sockaddr_in server, client;
int c;
//Intialising Winsock
wprintf(L"\\nInitialising Winsock...\\n");
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) {
wprintf(L"Failed. Error code : %d", WSAGetLastError());
return 1;
}
wprintf(L"Initialised.\\n");
//Create Socket
if ((s = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {
wprintf(L"Could not create socket : %d", WSAGetLastError());
}
wprintf(L"Socket Created\\n");
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(8888);
//Bind
if (bind(s, (struct sockaddr*)&server, sizeof(server)) == SOCKET_ERROR) {
wprintf(L"Bind failed with error code : %d ", WSAGetLastError());
}
puts("Bind done");
//Listening to incoming connections
listen(s, 3);
//Accept and incoming connection
puts("Waiting for incoming connections...");
c = sizeof(struct sockaddr_in);
new_socket = accept(s, (struct sockaddr*)&client, &c);
if (new_socket == INVALID_SOCKET) {
wprintf(L"accept failed with error code : %d", WSAGetLastError());
}
puts("Connection accepted");
closesocket(s);
WSACleanup();
return 0;
}
- 실행결과
연결 대기 중인 8888포트로 telnet 연결을 시도하면 클라이언트 프로그램은 “Connection accepted” 메시지와 함께 프로세스가 종료된다.
!참고 연결 시점에 클라이언트의 IP 정보를 알 수 있다.
클라이언트의 sock 구조체에 IP 주소가 담긴다. 아래의 코드를 활용한다
char *client_ip = inet_ntoa(client.sin_addr);
int client_port = ntohs(client.sin_port);
포트를 바인딩하고 연결을 대기한 후 연결이 되었을 때 즉시 종료하는 프로그램을 작성하였다. 하지만 이는 생산적이지 못하다. 연결이 성립된 이후에는 많은 동작을 수행할 수 있다. 클라이언트에서 응답을 전송하도록 수정한다.
puts("Connection accepted");
message = "Hello Client! I have received your connection. But I have to go now, bye\\n";
send(new_socket, message, strlen(message), 0);
getchar();
closesocket(s);
WSACleanup();
Live Server
int __cdecl main(int argc, char** argv)
{
WSADATA wsa;
SOCKET s, new_socket;
struct sockaddr_in server, client;
int c;
const char* message;
//Intialising Winsock
wprintf(L"\\nInitialising Winsock...\\n");
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) {
wprintf(L"Failed. Error code : %d", WSAGetLastError());
return 1;
}
wprintf(L"Initialised.\\n");
//Create Socket
if ((s = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {
wprintf(L"Could not create socket : %d", WSAGetLastError());
}
wprintf(L"Socket Created\\n");
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(8888);
//Bind
if (bind(s, (struct sockaddr*)&server, sizeof(server)) == SOCKET_ERROR) {
wprintf(L"Bind failed with error code : %d ", WSAGetLastError());
}
puts("Bind done");
//Listening to incoming connections
listen(s, 3);
//Accept and incoming connection
puts("Waiting for incoming connections...");
c = sizeof(struct sockaddr_in);
while ((new_socket = accept(s, (struct sockaddr*)&client, &c)) != INVALID_SOCKET) {
puts("Connection accepted");
//reply to the client
message = "Hello Client! I have received your connection. But I have to go now, bye\\n";
send(new_socket, message, strlen(message), 0);
}
if (new_socket == INVALID_SOCKET) {
wprintf(L"accept failed with error code : %d", WSAGetLastError());
return 1;
}
closesocket(s);
WSACleanup();
return 0;
}
이 서버는 다운되지 않고 이제 항상 동작한다. 여러 연결 요청이 들어와도 새로운 소켓을 생성하여 연결을 유지할 수 있다.
반응형
'Reversing' 카테고리의 다른 글
[Frida] Windows Socket Program hooking (0) | 2022.05.26 |
---|---|
[Cheat Engine] Socket Program 분석 (0) | 2022.05.21 |
[C++] Windows Socket Programming 예제 (0) | 2022.05.13 |
[Frida] Hooking send(), recv() (0) | 2022.05.10 |
[Frida] Binary Hooking 2 (0) | 2022.05.03 |