Try Attack/python[basic]

python으로 Linux에서 zip파일 압축 및 해제

D4tai1 2019. 1. 19.

※ 이 글은 파이썬3을 기준으로 작성되었으니 참고하시기 바랍니다.

 

1. Linux에서 zip파일 압축 및 해제

(1) 압축 및 해제

 [1] unzip 패키지 설치

  ▶ [apt-get install unzip -y] 명령어로 unzip 패키지를 설치한다.

 

 [2] 압축

  ▶ [zip "생성할 압축파일명" "압축할 파일1" "압축할파일2"...] 명령어로 zip압축할 수 있다.

  ▶ -P 옵션을 사용해서 패스워드를 지정할 수도 있다.

 

 [3] 해제

  ▶ [unzip "압축파일명"]

 

 [4] 일반적인 압축 및 해제 시연

 

 

 

2. python으로 압축파일 해제(zipfile 모듈 사용)

(1) zip_crack1.py

 [1] 소스

import zipfile  zFile = zipfile.ZipFile("secret.zip") #zipfile모듈의 ZipFile()메서드를 호출 #ZipFile()메서드는 zip파일의 이름을 넣어준다.  zFile.extractall(pwd=b"456789") #zFile을 추출한다.  

   ▶ 7라인에 pwd의 값에 b를 붙인 이유는 str로 들어가지 않고 byte로 들어가기 때문이다.

 

 [2] 시연

  ▶ 만약 비밀번호가 틀리다면 여러 줄의 에러와 함께 돌아가지 않는 것을 확인할 수 있다.

  ▶ 오류가 발생할 가능성이 있기 때문에 (2)에서 예외처리를 해주려고 한다.

 

(2) zip_crack2.py

 [1] 소스

import zipfile  zFile = zipfile.ZipFile("secret.zip")  try:         zFile.extractall(pwd=b'999999') except Exception as e:     e = str(e).split()     it = iter(e)     for result in range(4):         print(next(it)+" ", end="")     print() 

  ▶ (1)의 소스와 동일하지만 try-except문을 추가하였다.

  ▶ except 부분은 그냥 print(e)로 처리해주어도 무방하다.

  ▶ 그러나 뒤에 보기 싫은 단어들이 우르르 달려있기 때문에 혹은 세부오류내용은 사용자에게 공개하는 것을 원치 않을 수도 있다.

  ▶ 그래서 e는 runtimeerror의 type이고 str로 변경 후 space를 기준으로 split(분할)하여 리스트로 변경하여 e에 재저장한다.

  ▶ 리스트로 for문을 돌려도 되지만 여기서는 iterator을 사용해보려고 한다.

  ▶ 이것을 그냥 찍으면 리스트형태로 찍히기 때문에 iterable객체를 iterator를 반환받아 사용한다.

  ▶ 객체.__next__() 메서드를 사용하거나 그냥 next(iterator객체)와 같이 사용하여도 무방하다.

  ▶ 쉽게 말하면 리스트에서 다음[next()메소드]을 4번 불러서 print(e[0], e[1], e[2], e[3]) 를 적은 것과 동일하다.

  ▶ print(e[:4]) 이렇게 적는다면 리스트형태로 찍히게 된다.

 

 [2] 시연

  ▶ Exception을 그냥 출력할 경우 우르르 에러메세지가 출력된다.

 

  ▶ (2) - [1] 과 같이 정제 후 출력한 경우는 나름 정제되었다.

  ▶ 압축파일의 패스워드가 일치한다면 (1) - [2]와 같이 출력된다.

 

(3) zip_crack3.py

 [1] 소스

import zipfile  zFile = zipfile.ZipFile("secret.zip")  for x in range (0, 1000000):     if x % 100000 == 0:         print("[*] Looking for password...", x)     if x < 10:          passwd = "00000" + str(x)        elif x < 100:         passwd = "0000" + str(x)     elif x < 1000:         passwd = "000" + str(x)     elif x < 10000:         passwd = "00" + str(x)     elif x < 100000:         passwd = "0" + str(x)     else:         passwd = str(x)      try:         zFile.extractall(pwd=bytes(passwd,'utf-8'))         print("[+] Found password = "+passwd)         exit(0)      except Exception as e:         pass 

  ▶ 압축파일의 비밀번호를 모를 때 찾기 위해 비밀번호가 6자리 숫자라고 가정하고 진행하였다.

  ▶ 만약 숫자가 아니라면 0~9, a~z, 특수문자를 리스트에 넣고 하나씩 꺼내와서...

  ▶ 비밀번호가 한자리일 때부터... 어... 무차별공격은 언젠가는 성공하니...  

  ▶ pwd는 byte type으로 변환 후 전달한다.

 

 [2] 시연

  ▶ 찾았음을 알 수 있다.

  ▶ 이 내용을 보기좋게 (4)에서 함수로 모듈화하려고 한다.

 

(4) zip_crack4.py

 [1] 소스

import zipfile  def extract(zFile, passwd):     try:         zFile.extractall(pwd = bytes(passwd, 'utf-8'))         return passwd     except Exception as e:         if passwd == '000000':             print("[-] Password not found...")         return   def check(x):     if x % 100000 == 0:         print("[*] Looking for password..."+str(x))     if x < 10:          passwd = "00000" + str(x)     if x < 100:         passwd = "0000" + str(x)     elif x < 1000:         passwd = "000" + str(x)     elif x < 10000:         passwd = "00" + str(x)     elif x < 100000:         passwd = "0" + str(x)     else:         passwd = str(x)     return passwd  def main():     zFile = zipfile.ZipFile("secret.zip")          for x in range(999999, -1, -1):         passwd = check(x)         guess = extract(zFile, passwd)          if guess:             print("[+] Found password = " + passwd)             exit(0)  if __name__ == '__main__': #__name__은 현재 모듈이 메인이면?     main() 

  ▶ (3)의 내용을 함수화 하였다.

 

 [2] 시연

  ▶ 함수로 작성해도 정상적으로 동작한다.

  ▶ (5)에서는 압축파일 이름을 인자로 입력받으려고 한다.

 

(5) zip_crack5.py

 [1] 소스

import zipfile import sys  #system모듈  def extract(zFile, passwd):     try:         zFile.extractall(pwd = bytes(passwd, 'utf-8'))         return passwd     except Exception as e:         if passwd == '999999':             print("[-] Password not found...")         return   def check(x):     if x % 100000 == 0:         print("[*] Looking for password..."+str(x//100000)+"0%")     if x < 10:          passwd = "00000" + str(x)     if x < 100:         passwd = "0000" + str(x)     elif x < 1000:         passwd = "000" + str(x)     elif x < 10000:         passwd = "00" + str(x)     elif x < 100000:         passwd = "0" + str(x)     else:         passwd = str(x)     return passwd  def main():     try:         zFile = zipfile.ZipFile(sys.argv[1])     except Exception as e:         print('\"'+sys.argv[1]+'\"'+ 'is not found!!')         exit(0)          for x in range(0, 1000000):         passwd = check(x)         guess = extract(zFile, passwd)          if guess:             print("[+] Found password = " + passwd)             exit(0)  if __name__ == '__main__': #__name__은 현재 모듈이 메인이면?     main() 

  ▶ sys를 import한다.

  ▶ 이유는 압축파일 이름을 파라미터로 입력받기 위해서이다.

  ▶ 소스는 (4)와 거의 동일하며 기존파일 이름부분이 sys.argv[1]로 작성되었다.

  ▶ def check(x): 부분에서 출력 시 %로 출력되도록 변경하였다.

  ▶ 또한 압축파일명을 파라미터로 입력받기 때문에 잘못 입력받으면 에러가 발생할 수 있다.

  ▶ 그래서 def main(): 부분에서 try-except문을 추가하였다.

 

 [2] 시연

  ▶ 올바른 압축파일명을 입력하면 정상적으로 동작한다.

  ▶ 있지않은 압축파일명을 입력하면 에러를 출력한다.

 

(6) zip_crack6.py

 [1] 소스

import zipfile import sys  #system모듈 from colorama import init, Fore, Back  init(autoreset = True) #한 줄이 끝나면 색깔 초기화!!  def extract(zFile, passwd):     try:         zFile.extractall(pwd = bytes(passwd, 'utf-8'))         return passwd     except Exception as e:         if passwd == '999999':             print("[-] Password not found...")         return   def check(x):     if x % 100000 == 0:         print("[*] Looking for password..."+str(x//100000)+"0%")     if x < 10:          passwd = "00000" + str(x)     if x < 100:         passwd = "0000" + str(x)     elif x < 1000:         passwd = "000" + str(x)     elif x < 10000:         passwd = "00" + str(x)     elif x < 100000:         passwd = "0" + str(x)     else:         passwd = str(x)     return passwd  def main():     try:         zFile = zipfile.ZipFile(sys.argv[1])     except Exception as e:         print(Fore.YELLOW + Back.RED+'\"'+sys.argv[1]+'\"'+ 'is not found!!')         exit(0)          for x in range(0, 1000000):         passwd = check(x)         guess = extract(zFile, passwd)          if guess:             print(Fore.GREEN + "[+] Found password = " + passwd)             exit(0)  if __name__ == '__main__': #__name__은 현재 모듈이 메인이면?     main() 

  ▶ 3라인 [from colorama import init, Fore, Back] 이 추가되었다.

  ▶ 조금 이쁘게 색을 넣기 위해서 colorama 모듈을 추가하였다.

  ▶ 만약 오류가 발생한다면 [python3 pip install colorame] 명령어로 모듈을 추가한다.

  ▶ print문 작성 시 Fore."색상", Back."색상"과 같은 양식으로 포그라운드(글자색), 백그라운드(배경색)의 색상을 지정한다.

 

 [2] 시연

  ▶ 에러 시에는 붉은 색, 패스워드를 찾은 경우는 녹색을 지정하였다.

  ▶ 필요에 따라 원하는대로 작성하면 좋을 것 같다.

 

댓글