지난 시간에 이어서 이번 시간에는 클라이언트(타겟팅 컴퓨터 혹은 내가 조정하고자 하는 컴퓨터)에서 실행시킬 코드를 다루어 보도록 하겠습니다.
우선 아래와 같이 필요한 모듈을 import 해줍니다. ▼
소켓을 실행시켜 변수 s 에 넣겠습니다.▼
서버(내 컴퓨터)의 아이피 주소를 호스트에 할당해 줍니다. 여기 있는 아이피로 클라이언트(숙주 컴퓨터)가 찾아오게 하는 겁니다. 물론 아래와 같이 자신의 아이피를 고스란히 누설하는 크래커는 없을 것입니다. 보통은 다른 루트를 여러번 경유하게 하거나, 중간에 다른 매개체(!!)를 거치게 합니다. 이 부분은 다루지 않겠습니다. 그러다 정말 철컹철컹 당할 사람을 만들면 안되겠기에.....;; 아래 아이피도 임의의 가상 아이피 입니다. 집에서 공유기를 사용하신다면, 192.168.x.x 이렇게 나오는 경우가 많은데 연습을 할 컴퓨터가 동일 공유기를 사용한다면 아무 문제가 없습니다. 반대일 경우에는.... 못찾겠죠? ▼
포트는 서버에서 정한 임의의 포트와 동일하게 적용하면 됩니다.▼
host, port 를 가지고 소켓을 연결시킵니다. ▼
종료하라는 명령이 들어오기 전에는 계속 돌려야 하므로, 특정 조건이 들어오기 전에는 무한 루프로 돌립니다.▼
소켓의 버퍼 사이즈를 2048로 정하고 data 변수에 넣습니다.▼
만얀 CLI(Command Line Interface) 에서 처음 두 글자가 'cd' -> change directory 인 경우에는 어떻게 하겠다라는 조건문입니다. ▼
명령어 처음 두 문자가 'cd' 이면 보통 'cd directory_path' 이런식인데, 빈칸이 cd는 0,1 포지션 값이고 스페이스(빈칸)이 2 포지션 값이 됩니다. 그래서 아래와 같이 3번째 포지션 값부터 끝까지 경로값으로 디렉토리를 체인지 하는 코드를 넣습니다.▼
그리고 data의 길이가 0 초과, 즉 어떤 값(명령)이 들어오면 아래 코드를 실행하게 합니다. ▼
아래 코드는 파이썬에서 shell script 명령어를 실행 시킬때 사용하는 subprocess 모듈을 이용하였습니다. 그 명령값을 cmd 변수에 저장하였습니다.▼
cmd 의 stdout 과 stderror을 읽어 output_bytes 에 넣어줍니다. 여기서 output_bytes 값은 사람이 읽을수 없는 이진 비트(0100011110001010)과 같은 수입니다.▼
그래서 위의 이진 비트의 값(바이트)들을 인간이 읽을 수 있는 값으로 "utf-8" encoding 을 이용하여 스트링버전으로 만들어 줍니다. 그 값을 output_str 에 저장합니다.▼
이렇게 클라이언트에서 실행된 값을 서버로 다시 보내주는 코드를 아래와 같이 만들었는데, 뒷부분은 현재 작업이 이루어지고 있는 terminal 의 경로도 함께 보내주게 합니다. 이렇게 함으로써 서버(내 컴퓨터)에서 상대방(클라이언트)의 어느 경로에서 명령이 수행되고 있는지도 알게 됩니다. ▼
그리고 아래 프린트 아웃한 부분은 클라이언트(숙주 컴퓨터)에도 보여지게 하였습니다. 실제로는 숙주컴퓨터의 사용자가 모르게 할 의도라면 이와같은 우매한 짓은 하지 않겠지만, 우리는 연습이므로 숙주컴(클라이언트)에서도 어떤일이 일어나고 있는지 확인하는 차원에서 아래와 같이 프린트 문을 넣었습니다. ▼
여기까지 진행하였다면, 이제 소켓을 닫아주기만 하면 됩니다.▼
이제까지 만든 서버측(내 컴퓨터) 코드와 클라이언트(숙주 or 타겟) 컴퓨터 코드를 만들어 보았습니다. 이제는 실행을 통해 어떻게 작동하는지 간략히 알아보겠습니다.
우선 앞서 만든 서버측 코드를 실행합니다. 그러면 아래와 같은 화면이 나오고, 대기하고 있습니다. 무엇을 대기하냐면, 클라이언트가 내 컴퓨터로 접속을 해오기를 기다리고 있는 것입니다.▼
이번에는 클라이언트 코드를 실행합니다. 그러면 아래와 같은 화면이 나타나게 됩니다.▼
다시 서버 실행 화면으로 넘어가 보면, 클라이언트에서 방금 코드를 실행하여 서버(나에게)에게 접속을 해 왔기 때문에, 클라이언트의 아이피 주소와 접속 포트가 나타나게 됩니다. 즉 내가 마음대로 다루어 줄(?) 컴퓨터의 아이피는 아래와 같은 곳에 위치하고 있는 컴퓨터입니다.▼
현재 이 컴퓨터는 맥에서 구동하고 있기 때문에 'ls' -> list 명령어를 내리면 현재 폴더에 있는 파일들을 보여줍니다. 현재는 아래와 같이 2개가 있군요. 윈도우즈를 사용하는 환경이라면 'dir' 을 넣으면 됩니다. 리눅스도 'ls' 를 넣으면 됩니다.▼
이번에는 클라이언트로 넘어가 보니 서버에서 넣은 명령값에 클라이언트가 서버로 보내준게 무엇인지 보여주고 있습니다. 다시 말하지만, 이는 연습을 위한 것이기에, 보이게 하는 것입니다. ▼
다시 서버로 돌아와서 현재 작업이 이루어 지고 있는 경로가 어디인지 묻는 명령어인 'pwd' 넣으니 어디라고 알려주네요.▼
다시 클라이언트로 화면을 넘겨보니 서버로 보내준 데이터가 뭔지 이미 나타나 있습니다.▼
이번에는 서버에서 임의의 파일을 만들게 하는 명령어를 넣어 보겠습니다.▼
그리고는 클라이언트 컴퓨터에 있는 파일들이 무엇무엇이 있는지 자세하게 살펴보았습니다.▼
다시 클라이언트로 돌아와보니 서버로 몰래 전달된 데이터가 무엇인지 보여집니다.▼
이상이 기본적인 리버스 쉘 이었습니다. 물론 실제 상황이라면 위와 같이 단순하지는 않습니다. 그러나 기본적인 개념을 익히기에는 충분하리라 봅니다. 그리고 상기 과정은 단 하나의 접속만을 허용하는 심플한 코드입니다. 자신의 컴퓨터로 연습을 해보시고, 2대 이상의 컴퓨터가 있다면 다른 컴퓨터에 클라이언트 코드를 실행하게 하게 옆방에서 클라이언트를 컨트롤 해 보는 것도 재미(?) 있는 놀이가 될 것입니다. 이상입니다.