파이썬(Python)/화이트해킹,침투테스트(Hack,Penetration)

(파이썬)subprocess, os.system, re.findall, re.search를 사용한 간단 예제 - wifi 비번찾기

끄적끄적아무거나 2021. 6. 8. 10:11
반응형

컴퓨터에 저장된 와이파이 비밀번호 파이썬으로 출력하기


예제의 목적 및 구현 방법

 

예제는 앞서 "cmd" 명령프롬프트로 구현한 wifi 비밀번호 찾기를 python으로 구현한것이다. 해당 예제는 괄호안에 링크를 참조하길 바란다. (https://scribblinganything.tistory.com/188)

 

cmd에서 우리가 사용하는 명령어를 쉘이라고 하고 파이썬에서는 쉘 명령어를 os 모듈 또는 subprocess 모듈에서 지원해 준다. os 모듈과 subprocess 모듈의 차이점은 사실 비전문가 입장에서 사용방법을 제외하고는 거의 유사하다. 

가령 나중에 나올 예제에서 chcp, netsh 라는 쉘명령어는 os.system에서 실행되지만 subprocess.run에서는 netsh은 되지만 chcp는 실행이 안된다. 그래서 내 생각엔 사용하고자하는 명령어에 따라 적절히 사용해주면 될 것 같다. 

 

정규식 함수 re의 findall 과 search 모두 검색에 사용되는데 사용하는 입장에서 가장 큰 차이는 return 값이다. findall에서는 검색값을 바로 return 하지만 search 의 경우 튜플에 저장해서 [1] 인덱스를 사용해서 받아야 한다. 

 

아래 간단한 예제를 통해 쉽게 이해해보도록 하자

 


와이파이 비번찾기 예제 

 

 

코드 - wifi.py>>

import subprocess
import re
import os

os.system("chcp 437") 
# os.system("netsh wlan show profiles")

network_profiles = subprocess.run(["netsh", "wlan", "show", "profiles"], capture_output = True)
print("###")
print(network_profiles)
SSID_names = (re.findall(" : (.*)\r", network_profiles.stdout.decode()))
print("###")
print(SSID_names)
id_pw = {}

if SSID_names:
    for SSID_name in SSID_names:
        SSID_info = subprocess.run(["netsh", "wlan", "show", "profile", SSID_name], capture_output = True).stdout.decode()
        if re.findall("Security key           : Present", SSID_info):
            password_visible = subprocess.run(["netsh", "wlan", "show", "profile", SSID_name, "key=clear"], capture_output = True).stdout.decode()
            password = re.findall("Key Content            : (.*)\r", password_visible)
            id_pw[SSID_name] = password
else:
    print("저장된 SSID가 없습니다")
print("###")
print(id_pw)

 

결과>>

Active code page: 437
###
CompletedProcess(args=['netsh', 'wlan', 'show', 'profiles'], returncode=0, stdout=b'\r\nProfiles on interface Wi-Fi:\r\n\r\nGroup policy profiles (read only)\r\n---------------------------------\r\n    <None>\r\n\r\nUser profiles\r\n-------------\r\n    All User Profile     : Galaxy Note10 *****\r\n    All User Profile     : Public WiFi Free\r\n    All User Profile     : fam*******\r\n    All User Profile     : fam******\r\n\r\n', stderr=b'')  
###
['Galaxy ************', 'Public WiFi Free', 'fam*****', 'fam*****']
###
{'Galaxy ************': ['08******5'], 'fam*****': ['1a2b3c'], 'fam*****': ['1a2b3c']}

 

 

주석>>

결과 부분에서 아이디와 비밀번호는 개인정보 보호를 위해 별표로 변경했다. 

 

우선 코드에서 "chcp 437" 를 os.system으로 실행하였다. 이는 cmd 창에서 실행하는 것과 동일한 결과인데 한글 컴퓨터에서 실행하면 한글과 섞여서 결과를 분석하기 힘들 때가 있다. chcp 437은 이를 영문으로 변경해준다. 만일 변경하지 않고 실행하면 아래와 같은 에러 메세지가 나온다. 

"UnicodeDecodeError: 'utf-8' codec can't decode byte 0xc0 in position 8: invalid start byte"

한글에서는 byte 값과 영어가 섞여서 나와서 decode 자체가 안되는 것이다. 

Decode를 없애도 영어와 byte 값이 섞여서 아래 처럼 에러메세지가 발생한다. 

"TypeError: cannot use a string pattern on a bytes-like object"

 

그래서 앞서 말한 것처럼 chcp 437을 사용해서 영문으로 변경하고 시작하는 것이 좋다. 다시 한글로 변경하고 싶다면 "chcp 949"를 입력하면 된다. 

 

다음으로 # os.system("netsh wlan show profiles") 주석 처리한 명력은 netsh 가 os.system으로 실행 가능하다는 것을 알려주기 위해 그냥 넣은 구문이다. 

      

subprocess.run(["netsh""wlan""show""profiles"], capture_output = True) 에서  capture_output 은 출력 값을 return으로 받겠다는 의미이다. 

 

그림1

그림1은 실제 cmd에서 실행한 것으로 위 결과를 return으로 받는 것이다. 

 

받은 결과 중에 SSID 이름 부분만 가져오기 위해 정규식을 이용하였다. 

re.findall(" : (.*)\r"network_profiles.stdout) 에서 인자 두번째 값 중에서 정규식 . 의 의미는 아무거나이고 *는 여러개를 의미한다. 그리고 \r이 나올때까지 괄호안 부분만 return 한다는 뜻이다. 

그결과 위에 결과 화면에서 볼수 있듯이 SSID 값을 가져 올 수 있었다. 

 

나머지는 유사한 방법으로 비밀번호를 가져온다. 비밀번호가 있는 지 유무를 확인하고 있다면 "key=clear"를 통해서 보이게 만든다음에 id_pw에 넣어주었다. 

 

반응형