'Wargame/pwnable'에 해당되는 글 3건

  1. 2017.07.25 [pwnable.kr] bof
  2. 2017.06.25 [pwnable.kr] collision
  3. 2017.06.18 [pwnable.kr] fd
Wargame/pwnable2017. 7. 25. 23:45

pwnable.kr 사이트의 bof 문제를 보면 다음과 같다.


download URL이 제공된다. 일단 다운로드를 받자.


c코드는 다음과 같다.

코드를 분석해보자.

1. main 함수 내에서 func 함수를 호출한다.

2. func 함수를 호출하면서 인자로 0xdeadbeef 를 전달한다.

3. func 함수는 인자로 int 형 변수 하나를 받는다.

4. func 함수 내에서 char형 배열 overflowme를 선언한다.

5. 변수명이 굉장히 노골적이다.

6. gets 함수를 호출해 overflowme 변수에 입력값을 저장한다.

7. 인자로 받은 값과 0xcafebabe를 비교한다.

8. 같으면 bash 실행

9. 다르면 Nah.. 출력


코드 분석을 통해 알아낸 것은 func 함수의 인자인 key 값을 변조해야 한다는 것이다.

그렇다면 어떻게 key 값을 변조할 수 있을까??

해답은 gets 함수에 있다.

gets 함수는 인자로 받은 변수에 데이터를 쓰는 함수인데, 사용자가 입력한 값을 문자열로 저장을 한다. 이 때, 변수의 크기를 넘겨서 쓸 수 있다. 즉, BOF가 발생한다.


payload를 어떻게 만들 수 있을까?

payload를 만들기 위해서는 우선 해당 프로그램을 disassemble 해야 한다.

필자는 ubunt에서 gdb 툴을 이용해 disassemble을 했다.


우선, bof 파일을 다운로드를 받은 뒤 gdb명령을 사용한다.

gdb -q bof

-q 옵션은 gdb 버전 정보 등을 출력하지 않는 옵션이라고 생각하면 된다.


set disassembly-flavor intel

이 명령어는 gdb 명령어로 intel 문법을 이용하도록 설정한다. gdb는 기본 문법이 AT&T이다.


다음 명령어로 main 함수를 디스어셈블 해보자.

disas main

main 함수를 디스어셈블해 보여준다.


main 함수의 스택을 표현하면 다음과 같다.


 

 0xdeadeef

 <-ESP

 

 

 

 

 

 

 

 

 

 EBP->

 SFP

 

 

 ret

 


func 함수를 호출할 때의 스택의 모습이다.


다음 명령으로 func 함수를 디스어셈블하면 다음과 같다.

disas func

func 함수를 디스어셈블해 보여준다.


이 함수에서 보아야 할 부분은 <+29>부터 <+35> 까지이다.

<+29>

overflowme 변수의 시작 위치와 크기를 알 수 있다.

<+32>

overflowme 변수를 esp에 저장하므로써 gets 함수 호출을 준비한다. 즉, 매개변수 설정

<+35>

gets 함수 호출


양이 조금 많아 보이지만 실제로는 작은 조각에 불과하다. 겁먹지 말고 일단 스택을 표현해보자.


 

overflowme 변수의 주소 

 <- ESP

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

overflowme 변수 메모리( 44바이트 ) 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

EBP -> 

 SFP

 

 

 ret

 

 

 func 함수의 매개변수 Key값

 


func+35 부분까지 진행 하면 위와 같이 스택을 표현할 수 있다.

ESP에 oveflowme 변수의 주소를 저장하고 gets 함수를 호출한다.

gets 함수가 반환이 되면 overflowme 변수에 입력된 값을 저장한다.

여기서 44바이트를 초과해서 입력을 해주면 아래 SFP, ret 그리고 func 함수의 매개변수인 key의 값까지도 변조가 가능하다.


key값을 변조하기 위해서 얼마나 입력해야 할까?

overflowme 변수는 44바이트 크기를 받았다. 여기에 더해 SFP, ret 까지 덮으면 그 다음이 key 값이다. 즉, 8바이트를 더한 52바이트를 입력한 후 다음 4바이트가 key값이 되는 것이다.


필자는 python을 이용해 payload를 작성했다.

payload는 다음과 같다.


(python -c 'print "A"*52 + "\xbe\xba\xfe\xca"'; cat) | nc pwnable.kr 9000


그 결과 bash/sh 이 실행이 됨을 볼 수 있다.

flag 를 읽어보자 



'Wargame > pwnable' 카테고리의 다른 글

[pwnable.kr] collision  (0) 2017.06.25
[pwnable.kr] fd  (0) 2017.06.18
Posted by Imp3rio
Wargame/pwnable2017. 6. 25. 19:15

pwnable.kr 사이트의 collision 문제를 보면 다음과 같다.

문제를 보니 MD5 해쉬 충돌과 관련된 문제인 것 같다.

해쉬 충돌이란 해쉬 함수가 서로 다른 두 개의 입력값에 대해 동일한 출력값을 갖는 것을 의미한다.


우선 ssh로 접속해 코드를 보면 다음과 같다.

우선 코드를 분석해보자.

main 함수를 보면 인자가 20바이트가 아니면 "passcode length should be 20 bytes" 문자열을 찍어내고 종료한다. 이를 통해 20바이트의 인자를 넘겨주어야 하는 것을 알 수 있다.

hashcode는 0x21DD09EC 이고, check_password() 함수의 결과 값이 hashcode와 같으면 문제가 풀리는 것 같다.


인자의 값이 0x21DD09EC와 같아야 하는데, 총 20바이트를 넘겨주어야 한다.

총 20바이트의 값이 0x21DD09EC( 4바이트 )와 같아야 하기 때문에 0x21DD09EC를 5로 나눈 값을 넘겨주면 된다.

0x21DD09EC를 5로 나누면 0x6C5CEC8이고, 0x6C5CEC8에 5를 곱하면 0x21DD09E8이 나온다.

즉, 4만큼 차이가 난다.

따라서 0x6C5CEC8 * 4 + 0x6C5CECC를 넘겨주면 된다.

이 값을 python 코드로 넘겨주도록 하자.

python -c 'print "\xC8\xCE\xC5\x06"*4+"\xCC\xCE\xC5\x06"'


위 코드를 인자로 넘겨주면 된다.

위와 같이 플래그가 툭 튀어 나온다.

이 값을 Auth에 넘겨주면 문제가 풀린다.

'Wargame > pwnable' 카테고리의 다른 글

[pwnable.kr] bof  (0) 2017.07.25
[pwnable.kr] fd  (0) 2017.06.18
Posted by Imp3rio
Wargame/pwnable2017. 6. 18. 18:38

pwnable.kr 사이트의 fd 문제를 열어보면 다음과 같은 화면을 볼 수 있다.


file descriptor에 대한 문제인 것 같다.

우선 ssh로 접속을 해보자.

fd, fd.c, flag 파일이 존재한다.

fd.c 파일을 열어보자.

fd.c 파일은 위와 같이 코딩되어 있다.

32 바이트 크기의 buf가 전역변수로 선언되어 있다.

fd 파일을 실행할 때 인자가 없으면 그냥 종료한다.

fd 변수에 1번째 인자 값에서 0x1234를 뺀 값을 저장하고

len 변수에 read()함수로 fd에 있는 값을 buf에 저장한 바이트 수를 저장한다.

buf에 저장된 문자가 LETMEWIN이면 system()함수로 flag 파일을 읽는다.


위에 분석한 내용을 가지고 문제를 풀어보자.


우선, file descriptor가 무엇인지 알아야 한다.

리눅스에서는 모든 프로세서는 file descriptor로 동작하게 된다.

file descriptor 중 0, 1. 2 는 시스템에서 사용하기 때문에 사용자가 실행하는 프로세서는 이 값을 제외한 값을 갖는다.


 0( standard input )

 키보드 입력을 받는다.

 1( standard output )

 입력된 값을 출력한다.

 2( standard error )

 에러 내용을 출력한다.


키보드 입력을 통해 buf에 LETMEWIN을 넣어야 하기 때문에 fd 변수에 저장되는 값이 0이 되어야 한다.

따라서 0x1234(4660)을 입력을 하면 키보드 입력을 받는다.


flag를 읽어온 것을 볼 수 있다. 이 값을 입력하면 문제가 풀린다.

'Wargame > pwnable' 카테고리의 다른 글

[pwnable.kr] bof  (0) 2017.07.25
[pwnable.kr] collision  (0) 2017.06.25
Posted by Imp3rio