모의해킹(Penetration Testing) PortScanner 6. 업그레이드1: 스레드를 활용한 고속 스캔

6.   업그레이드1: 스레드를 활용한 고속 스캔

 

성공적으로 포트 스캐너를 만들었지만 프로그램의 실행의 흐름은 하나이기 때문에 매우 느리다 포트의 스캔이 끝나야만 다음 포트를 스캔할  있기에 대기 시간이 상당히 길다는 단점이 존재한다만약  속도로 65536(0~65535)개의 포트를 모두 검사해야 된다면 여러분은 시간 내의 업무를 마치지 못할 수도 있다그렇다면 부득이하게 야근을 해야 하는 경우도 발생할 것이다.

 

이번에는 스레드를 활용하여 프로그램의 실행을 여러 개로 나누어 보자대상 서버로 요청을 한꺼번에 여러  보낸  여러 응답을 한꺼번에 기다리면 프로그램의 효율이 증가할 것이다.

 

스레드란  프로세스 내에서의 실행 흐름 단위를 이야기한다우리는 멀티 스레드 기법을 사용하여  프로세스 내에 여러 스레드가 존재하도록 만들 것이다.

 

 

 

 

1.png

 

그림 일반 포트 스캐너와 스레드 포트 스캐너의 차이

 

 

 

1)    세마포어(Semaphore)

 

스레드를 활용하기 위해서는 스레드를 제어할  알아야 한다. CPU 스레드를 돌아가며 실행하기 때문에 결과를 연속해서 출력하길 원하거나스레드의 수를 제어하기 원한다면(임계구역),  자원 원자성을 보호하기 원한다면 세마포어를 사용해야 한다세마포어는 특정 작업을 하는 동안에 (Lock) 걸어 임계구역을 설정하여 다른 스레드가 작업을 하지 않도록 제어한다언락(Unlock) 실행하면 다시 원래대로 동작한다.

 

많은 사람들이 세마포어를 보통 화장실에 비교하여 많이 설명한다 설명이 매우 단순하면서도 실제로 경험해보는 원리이기 때문에  이해할  있다.

 

변기 3대가 있는 화장실이 있다고 가정하자사람 10명이 와서  화장실을 사용하려고   10명이 모두 동시에  화장실을 사용할  없다한번에 3명만이 가능하다 3명은 화장실에 들어가 문을 걸어 잠그고(Lock),  사용한  문을 열고 나올 것이다(Unlock).   다음 사람들이 차례대로  화장실을 사용할  있을 것이다.






 

 

 

 

2.png

 

그림 10명의 사람들과 3개의 화장실

 

 

 

이러한 방식으로 스레드 생성량을 조절하지 않으면 프로그램은 스레드를  이상 만들  없다는 메시지를 출력하고 죽어버리니  주의하자먼저 실습을 통해 스레드의 동작 원리를 파악해 하자. time 라이브러리의 sleep함수를 사용하여 위에서 설명한 화장실 시뮬레이션을 직접 구현해보도록 한다. 아래 코드를 에디터 모드로 작성하여 실행([F5])하자.

 

 

 

 

 

 

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
#! python
# -*- coding: utf-8 -*-
# toilet simulation
 
import threading                       # 스레드 라이브러리
import time                                 # 시간 라이브러리
import random                               # 난수 라이브러리
 
numOfToilet = threading.Semaphore(value=3)  # 화장실이 3개 존재한다.
 
# 스레드 함수
def useToilet(peopleNum):                   # 스레드를 돌릴 함수를 정의해야 한다.
    time.sleep(random.randint(5,10))       # 화장실 사용 시간(5~10초 랜덤생성)
                                           #     해당 시간 동안 슬립
    print("he's happy now, people #" + peopleNum)
    numOfToilet.release()                   # 도어락 해제
    
# 메인 함수
def main():
    print("10 people start using 3 toilets...")
    for peopleNum in range(10):             # 10명의 사람들이 대기 중
        numOfToilet.acquire()               # 도어락 설정
        t=threading.Thread(target=useToilet, args=(str(peopleNum))) # 스레드 생성
        t.start()                             # 스레드 시작
    time.sleep(11)
    print("All People Happy~~~!!!")    # 모든 사람들 사용 종료
    
 
if __name__ =='__main__':
    main()
cs

 

결과 화면

 

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
10 people start using 3 toilets...
 
he's happy now, people #2 
he's happy now, people #0 
he's happy now, people #1 
he's happy now, people #3 
he's happy now, people #4 
he's happy now, people #5
he's happy now, people #7 
he's happy now, people #6 
he's happy now, people #8 
he's happy now, people #9 
 
All People Happy~~~!!!

cs

 

 

사람들의 사용 시간이 다르기 때문에 순서가 뒤죽박죽 진짜 화장실을 사용한 것처럼 결과가 실시간으로 출력된다. 3명만이 동시에 사용할  있기 때문에 중간에 사람이 나오면 다음 사람이 들어가 화장실을 사용할  있게 된다아래 그림을 통해서  결과를 조금  자세하게 이해해보기 바란다.

 

 

 

3.png

 

 

 

 실행 시간을 정확히 측정하지 못해 정확하지는 않지만 대략 이러한 흐름으로 흘러갔을 것이라 예상할  있다. #2 끝나면 #3 시작하고, #0 끝나면 #4 시작하고, #1 끝나면 #5 시작한다. #9 실행될 때까지  반복 작업을 수행한다.

 

 

 

새롭게 등장한 코드들에 대해서 살펴보자.

 

 

 

numOfToilet = threading.Semaphore(value=3)

 

threading.Semaphore함수의 인자 값을 3으로 세팅하여  번에 실행될  있는 스레드의 개수를 3개로 제한 했다.

 

 

 

time.sleep(random.randint(5,10))

 

time.sleep(s) s 만큼 스레드가 슬립(대기상태로 머물게 한다. s int  대신에 random.randint(5,10) 넣었다 함수는 5~10초를 랜덤으로 생성하여 int 값으로 반환한다 5~10 int 값을 생성하여 time.sleep(s) 인자로 넘겨 5~10 동안 스레드가 쉬도록 하는 코드이다.

 

 

 

경축! 아무것도 안하여 에스천사게임즈가 새로운 모습으로 재오픈 하였습니다.
어린이용이며, 설치가 필요없는 브라우저 게임입니다.
https://s1004games.com

print "\nhe's happy now, people #" + str(peopleNum),

 

 마지막 문자인 ‘,’(쉼표) 오타가 아니다쉼표를 입력하면 문자열 마지막에 newline 대신에 공백을 삽입한다위의 결과는 거의 동일하다굳이 이렇게 다른 방식으로 출력하는 이유는 스레드를 여러  실행하면 print 함수가  번에 실행되지 않고 문자열 출력과 새로운  출력을 나눠서 실행하는 경우가 있기 때문이다그러면 결과 출력  결과가 지저분하게 섞여서 출력된다 코드처럼 쉼표와 ‘\n’ 삽입하면 모든 문자열을 한번에 출력하여 문자열과 newLine 뒤섞이지 않고  출력된다.

 

 

 

numOfToilet.acquire()

 

numOfToilet.release()

 

 코드들은 미리 정의한 numOfToilet 스레드 개수를 추가하고 줄인다. acquire() 함수를 실행하여 실행 중인 스레드가 3개가 되면  이상 진행하지 않고 대기하다가실행 중이던 스레드가 release() 함수를 실행하여 스레드 개수가 줄어들면 다시 코드를 진행시킨다.

 

 

 

t=threading.Thread(target=useToilet, args=(str(peopleNum)))

 

t.start()

 

Thread() 함수는 변수 t 만들어 스레드 객체를 생성한다. target에는 위에서 미리 정의한 함수인 useToilet 값을 넣었고, args에는 함수에 넘겨줄 파라미터를 넣었다. t.start() 스레드를 실행한다.

 

 

 

 

 

2)    멀티 스레드 포트 스캐너

 

지금까지 세마포어에 대하여 공부해보았다이제  세마포어를 활용하여 포트 스캐너에 접목시켜보자여기서는  가지의 세마포어를 생성하였다세마포어 화장실 예제에서 사용한 세마포어처럼 스레드 개수를 제한하는 세마포어와 출력이 뒤섞이지 않도록 제어하는 세마포어를 사용하겠다마지막에는 결과를 csv 파일로 저장하고콘솔에도 출력하도록 하겠다.

 

 

 

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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#! python
# -*- coding: utf-8 -*-
# PortScanProgram with threads
 
import threading                                    # 스레드 관련 라이브러리
import socket                                       # 소켓 관련 라이브러리
import time                    # 시간 라이브러리
 
resultLock = threading.Semaphore(value=1)    # 결과 출력을 제어할 세마포어
maxConnection = 20                # 스레드 개수를 제어할 세마포어
connection_lock = threading.BoundedSemaphore(value=maxConnection) 
portList = []                    # 결과를 저장할 리스트1
dataList = []                    # 결과를 저장할 리스트2
 
# 스레드 함수
def scanPort(tgtHost, portNum):
   try:                        # 접속 시도
      s=socket.socket()
      s.settimeout(2)
      
      s.connect((tgtHost, portNum))
      s.send("Python Connect\n")
   
      data = s.recv(1024)
      resultLock.acquire()            # 결과 저장을 위해 세마포어 설정
      if data:                              # 데이터가 존재할 때 출력 및 저장
         print("[+] Port " + str(portNum) + " open: " + data[:20])
         portList.append(portNum)
         dataList.append('exist data')
      else:                    # 데이터가 존재하지 않을 때 출력 및 저장
         print("[+] Port " + str(portNum) + " open: no data")
         portList.append(portNum)
         dataList.append('no data')
      resultLock.release()            # 세마포어 해제
except:
      pass
   finally:
      s.close()
      connection_lock.release()            # 세마포어 해제
 
# 메인 함수
def main()
   tgtHost = "192.168.157.133"                  # 스캔 대상 tgtHost
    
   for portNum in range(65536):                    # 반복문 수행 0~65535 포트
      connection_lock.acquire()
      t = threading.Thread(target=scanPort, args =(tgtHost, portNum))    # 쓰레드 초기화
t.start()                    # 스레드 실행
      if portNum == 65535:             # 마지막 스레드 실행 후 결과를 기다림
         time.sleep(10)
 
   # csv 파일 저장
   f=open("portScanResult.csv",'w')                 # 결과를 저장할 csv 파일 열기
   f.write("portNum, banner\n")                      # 컬럼 쓰기
   for i in range(len(portList)):               # 결과 쓰기
      f.write(str(portList[i]) + ',' + dataList[i] + '\n')
   f.close()                                       # 파일 닫기
 
   # 결과 출력
   print "\n\n\n+++++++++++ the result +++++++++++"
   print('portNum' + '\t' + 'banner')
   for i in range(len(portList)):       
      print(str(portList[i]) + '\t' + dataList[i])
   print "\n\n\n>>>>>>>>> the result in portScanResult.csv"
 
if __name__ == "__main__":
   main()
 
cs

 

 

 

 

 

결과 화면 콘솔

 

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[+] Port 21 open220 (vsFTPd 2.3.4
 
[+] Port 23 open: ÿýÿý ÿý#ÿý'
[+] Port 25 open220 metasploitable.l
[+] Port 80 open<!DOCTYPE HTML PUBLI
...중략...
 
+++++++++++ the result +++++++++++
portNum    banner
22    exist data
21    exist data
23    exist data
25    exist data
80    exist data
... 중략...
 
 
>>>>>>>>> the result in portScanResult.csv
cs

 

 

 

 

 

 

 

 

결과 화면 : csv파일

 

 

 

 4.png

 

 

 

실행([F5])  결과를 기다리면 번째 만들었던 스캐너와는 비교할  없는 속도로 스캔을 시작한다하지만 65535포트를 모두 스캔하는 데에는 시간이  필요하니 1000 포트 정도만 스캔하도록 하자만약 눈에 띄게 결과를 확인하고 싶다면  예제 모두 같은 리스트를 대상으로 스캔하면 결과를 확인하기 쉽다.

 

 

 

※ 시간 기록하기

 

시간의 결과를 확인하기 쉬운 방법은 시간을 기록하는 것이다아래 코드와 같이 time 라이브러리의 time 함수를 사용하면 시작 시간과 마침 시간을 저장할  있다마침 시간에서 시작을 감산하여 출력하면  프로그램의 수행시간을   있다다음 예제부터는 프로그램 수행 시간을 출력하도록 구성하겠다.

 

 

 

1
2
3
4
5
6
startTime = time.time()
 
... 프로그램 수행 ...
 
endTime = time.time()
print “executed Time : ” + (endTime-startTime)
cs

 

 

 

 

 

  • csv 파일

 

csv 파일은 엑셀로 바로 결과를 출력할  있다업무  엑셀을 사용하는 경우가 많으니 이를 사용하면 업무를  효과적으로 처리할  있다형식은 매우 단순하다. MS 엑셀은 열은 쉼표(,) 구분하고 행은 newLine으로 구분한다.

 

 

[출처] https://m.blog.naver.com/isc0304/220373652138

 

 

 

본 웹사이트는 광고를 포함하고 있습니다.
광고 클릭에서 발생하는 수익금은 모두 웹사이트 서버의 유지 및 관리, 그리고 기술 콘텐츠 향상을 위해 쓰여집니다.
번호 제목 글쓴이 날짜 조회 수
공지 침투테스트(취약점검점검, 모의해킹) 문의 / 답변 졸리운_곰 2017.12.10 26654
292 [정보보호] 와이어샤크(Wireshark) 사용법 #2 [인터페이스] file 졸리운_곰 2023.07.30 6
291 [정보보호] 와이어샤크(Wireshark) 사용법 #1 [설치] file 졸리운_곰 2023.07.30 9
290 [정보보호] [2023 디도스 대응 리포트] 디도스 융단폭격에 기업·기관 ‘휘청’ file 졸리운_곰 2023.07.28 8
289 웹페이지 과다 호출 방식의 DDoS공격 사례 및 대처 졸리운_곰 2023.07.28 4
288 [ 一日30分 인생승리의 학습법] HTTP GET Flooding 공격이란? file 졸리운_곰 2023.07.28 7
287 [ 一日30分 인생승리의 학습법] DDoS 공격 대처 및 방어 file 졸리운_곰 2023.07.27 5
286 [ 一日30分 인생승리의 학습법] [ Apache ] DDoS 공격 대응( evasive 모듈,IP 제한 ) 졸리운_곰 2023.07.27 11
285 [보안뉴스] 당신 폰을 훤히 들여다본다... ‘백도어 해킹’의 신무기 스파이칩 file 졸리운_곰 2023.03.26 16
284 모의해킹(Penetration Testing) PortScanner 참고문헌 졸리운_곰 2023.03.20 9
283 모의해킹(Penetration Testing) PortScanner 8. 업그레이드3 : optparse 기능 졸리운_곰 2023.03.20 11
282 모의해킹(Penetration Testing) PortScanner 7. 업그레이드2 : Nmap 활용 file 졸리운_곰 2023.03.20 6
» 모의해킹(Penetration Testing) PortScanner 6. 업그레이드1: 스레드를 활용한 고속 스캔 file 졸리운_곰 2023.03.20 7
280 모의해킹(Penetration Testing) PortScanner 5. 포트 스캔 실행! file 졸리운_곰 2023.03.20 5
279 모의해킹(Penetration Testing) PortScanner 4. 취약한 공격 대상 만들기 file 졸리운_곰 2023.03.20 4
278 모의해킹(Penetration Testing) PortScanner 3. 필요한 기술 익히기 졸리운_곰 2023.03.20 2
277 모의해킹(Penetration Testing) PortScanner 2. 포트 스캐너를 위한 네트워크 기초 다지기 file 졸리운_곰 2023.03.20 5
276 모의해킹(Penetration Testing) PortScanner 1. 포트 스캔이란? 졸리운_곰 2023.03.20 8
275 [보안뉴스] 전 세계에서 가장 흔한 20개의 비밀번호는 무엇? file 졸리운_곰 2022.11.29 1
274 모의해킹(Penetration Testing) [Kali Linux] Kali Linux 명령어 | 배워야 할 기본 사항 file 졸리운_곰 2022.11.18 22
273 모의해킹(Penetration Testing) 칼리리눅스 사용법 file 졸리운_곰 2022.11.18 12
대표 김성준 주소 : 경기 용인 분당수지 U타워 등록번호 : 142-07-27414
통신판매업 신고 : 제2012-용인수지-0185호 출판업 신고 : 수지구청 제 123호 개인정보보호최고책임자 : 김성준 sjkim70@stechstar.com
대표전화 : 010-4589-2193 [fax] 02-6280-1294 COPYRIGHT(C) stechstar.com ALL RIGHTS RESERVED