달력

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

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







※ 사전지식 


이 문제에서 필요한 사전지식은 파이프라인과 ARM 아키텍쳐의 두 종류의 모드에 대한 것이다. 


그럼 하나씩 살펴보도록 하겠다. 



파이프라인 


CPU는 클록 신호에 따라 명령을 처리하게 설계되어 있다. 하지만 이 파이프라인이라는 메커니즘을 적용하면 주어진 클록 속도보다 더 빠르게 처리할 수 있게 된다. 기본 명령어는 순차적으로 명령을 처리하기 전에 일련의 종속 단계로 니뉘어져 서로 다른 단계가 병렬로 실행될 수 있다. 


위 내용을 받아드리기 쉽게 좀 구체화시켜 정리해보도록 하겠다. 


보통 파이프라인에 대한 설명을 할 때 우리는 명령 처리 단계를 4단계(CPU 아키텍쳐에 따라 다양함)로 나누어 설명하곤 한다. 


1. Instruction Fetch     : 다음에 실행할 명령어를 읽는다.

2. Instruction Decode  : 명령어를 해석한다.

3. Execute                 : 명령어를 수행한다.

4. Write-Back             : 처리된 결과를 저장한다.


위 순서대로 잘 설명되어 있는 내용을 찾아서 이를 그림에 맞춰 순서대로 정리해보겠다. 





상단의 회색 박스는 실행되기를 기다리는 명령어의 리스트이고 아래의 회색 박스는 실행이 완료된 명령어의 리스트이다. 중간의 하얀 박스가 바로 파이프라인이다. 


명령어들이 어떻게 실행되는지 싸이클 몇 개를 통해 알아보도록 하겠다. 


§ 0 Cycle

 4개의 명령어가 실행되기를 기다린다.

§ 1 Cycle

 녹색 명령어는 메모리로부터 패치된다.

§ 2 Cycle

 녹색 명령어는 디코드된다.

 보라색 명령어는 메모리로부터 패치된다.

§ 3 Cycle

 녹색 명령어는 실행된다. (실제 명령이 실행된다)

 녹색 명령어는 디코드된다.

 파랑 명령어는 페치된다.

§ 4 Cycle

 녹색 명령어는 결과적으로 레지스터나 메모리에 쓰인다.

 녹색 명령어는 실행된다.

 파랑 명령어는 디코드된다.

 빨강 명령어는 패치된다.


이제 파이프라인이란 개념이 어떤건지 좀 명확해졌을거라 믿는다. 

즉, 하나의 명령어를 처리할 수 있는 여러 단계로 나누어 종속된 일련의 명령어들이 처리되는 것에 있어 서로에게 영향을 주지 않는 범위에서 동시에 다른 명령어를 처리할 수 있는 것이다.

예를 들면, ADD 명령어와 MOV 명령어가 존재할 경우 처음 ADD 명령어를 Fetch 한 뒤 ADD 명령어가 다 처리되기도 전에 다시 MOV 명령어가 다시 Fetch 단계로 진입되게 되는 것이다. 


따라서 PC(Program Counter)는 단순히 다음 명령어를 나타내기 보단 Fetch를 진행해야 하는 위치를 나타낸다고 하는게 더 옳은 표현이다(파이프라인 기술이 도입된 아키텍쳐의 경우).




ARM vs Thumb Mode 


이 문제풀이에서 가장 크게 눈여겨봐야 할 것은 아래 두줄로 설명 가능하다. 

ARM : 32bit RISC Machine 

Thumb : 16bit RISC Machine 


아래 레퍼런스에 추가해놓은 사이트(ref.2)에 따라 추가로 설명하자면,

처음 32 bit ARM 만들어 냈을  세상을 지배하던 Embedded system memory 16 bit data line 가진 Memory  시대의 주인공 이었슴다. 32 bit Core라고 해서  시대에 가장 흔히 구할  있고 많이 생산되던 16bit bus line 메모리를 무시할 없는 노릇이었지요.


해서 나타난 게 Thumb 모드라고 한다. 


사전지식 끝!!





※ 문제풀이 



그럼 이제 문제풀이를 시작해보겠다. 

이 문제는 위에 사전지식에서 보았듯이 파이프라인과 ARM, Thumb 모드에 관련된 지식, 그리고 약간의 ARM 어셈블러를 해석할 수 있으면 풀 수 있는 문제이다. 


우선 문제를 한번 보자. 



크기상 우선 메인함수만 캡쳐해왔다. 

key1 함수, key2 함수 그리고 key3 함수의 결과 값을 합쳐 내가 입력한 값과 비교하는 문제이다. 


그럼 key? 함수가 어떤 값을 반환하는 지 알아보도록 하자.


우선 key1 함수이다.



현재 pc 레지스터에 있는 값을 r3로 옮기고 난 뒤 반환한다. 

위에서 설명한 파이프라인을 보았으면 이제 pc가 가리키는 값이 0x0008cdc라고 생각하지 않을거라 믿는다. :)


그 다음은 Key2 함수이다. 

 


여기에서는 key+12 위치에 있는 add 명령어와 bx 명령어를 잘 확인해야 한다. bx는 분기명령어 중 하나인데 피연산자의 0번째 비트의 값을 확인하여 1일 경우 Thumb 모드로 진입하게 된다. 그렇게 되면 pc를 계산하는 값이 Thumb 모드에 맞춰 변경되게 될 것이다. 그럼 뭐 key2 함수에서 어떤 값을 반환할 지도 예측 가능하지 않은가?!


그리고 마지막 key3 함수는 



이와 같다. lr은 리턴 주소값을 가지고 있는 레지스터이다. 이것은 직관적이니까 넘어가도록 하겠다. 


그럼 이 값을 다 더한 값이 곧 정답이다.


문제풀이 끝!!!



사실 이 leg 문제까지는 문제를 직접 풀어보려하지 않고 인터넷을 먼저 검색해서 어떤 것이 문제의 핵심인지 파악하고 나서 접근했다. 다시 일을 시작하게 되니 이런 저런 고민하는 시간이 너무 아쉬워서 단순 학습의 개념으로만 만족했었다. 어째든 이 문제까지 풀어본 바(학습해본 바?^^) 여러가지 그러려니 했던 많은 내용들을 구체화시키고 포너블이라는 영역이 어떤것인지 대충 개념은 잡을 수 있었다(기초적인 거에도 쩔쩔매던 놈이-ㅅ-). 


앞으로는 시간있을 때마다 스스로 고민해서 풀어봐야겠다. 

화이팅~~!!




Reference 

[1] Instruction pipelining, https://en.wikipedia.org/wiki/Instruction_pipelining

[2] ARM mode와 THUMB mode, http://recipes.egloos.com/4985218

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

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

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








이 문제는 문제풀이를 바로 들어가는 게 설명하기가 더 쉬울 것 같다. 


문제의 요지는 프로그램에 다양한 방법으로 입력 값을 전달하는 방법을 알고있는지에 대해 물어보는 것이다. 

하나씩 나열해보자면 아래와 같다. 

 

1. 메인함수 파라미터로 전달

2. 파일 디스크립터를 이용한 전달 

3. 환경변수를 통한 전달

4. 파일을 통한 전달

5. 네트워크 통신을 통한 전달 


부분적으로 하나씩 알아보자. 


[문제]

위는 메인함수의 파라미터로 전달된 파라미터 중 'A' 번째와 'B' 번째의 값을 비교하는 것이다. 

이는 아래와 같은 방법으로 우회할 수 있다. 


[해답]


위 코드는 파라미터에 요구된 값을 설정하는 부분이다. 

그 다음 문제를 확인해보자. 순착적으로 위에서 언급한 2번과 3번 문제에 해당한다. 


[문제]



여기에는 파이프 함수를 이용하여 파일 디스크립터 쌍을 생성하고 쓰기 파일디스크립터에 문제에서 제시한 값을 작성하고 읽기 파일디스크립터를 문제에서 제시한 0, 2 파일디스크립터로 각각 변경해주는 것이다. 

이는 아래와 같다. 


[해답]


그리고 환경 변수 값을 설정해준 뒤 부모 프로세스에서 문제의 프로그램을 execve 함수를 사용하여 호출한다.


이어서 파일에 값이 존재하는지 비교하는 함수가 존재한다.


[문제]


이는 간단히 파일 쓰기로 우회가 가능하다.

[해답]


그리고 마지막 문제는 소켓 통신 관련 문제이다. 

[문제]


이 문제는 소켓 프로그래밍을 이용하여 오픈된 포트로 접근한 뒤 요구하는 값을 전달해주면 된다. 단 여기서 포트로 사용되는 값은 최초 메인 함수에 전달된 값 중 'C' 번째에 전달된 값을 기반으로 생성된다. 


[해결]


흐름을 잘 조합하면 해당 문제가 클리어될 것이다. 


문제풀이 끝!!!



프로세스에 다양한 방법으로 입력 값을 전달하는 방법에 대해 알아볼 수 있었다.  :)





Reference

[1] Pwnable.kr - input, https://werewblog.wordpress.com/2016/01/11/pwnable-kr-input/

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

[문제풀이] pwnable.kr - unlink  (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
[문제풀이] pwnable.kr - passcode  (0) 2017.07.09
:
Posted by einai
2017. 7. 9. 15:09

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






※ 사전지식 



PLT(Procedure Linkage Table)


외부 프로시저를 연결해주는 테이블이다. 이는 동적 링크 환경에서 함수를 호출할 때 중요한 역할을 하게 된다.



GOT(Global Offset Table)


이 테이블은 프로시져들의 주소를 가지고 있다. 이 테이블은 PLT가 참조하는 테이블이다. 프로그램에서 외부 프로시저를 호출할 때 이 GOT를 참조해서 해당 주소로 점프하게 된다. 해당 테이블은 함수가 처음으로 호출될 때와 그 외에 호출될 때에 다른 값을 가지고 있다. 즉 런타임시 변경되는 값이다. 




우선 해당 문제에 필요한 지식 정도만 공부해도록 하겠다. 

한번에 이런저런걸 너무 많이 검색해서 보니 정리가 잘 안되는 느낌이다. - ㅅ-/



함수를 호출할 때 흐름을 따라가면서 하나씩 살펴보도록 하겠다.



이는 간단히 printf 함수를 두번 호출한 테스트 프로그램이다. 이를 컴파일(not static way)하여 GDB로 분석해보겠따. 



위는 GDB로 메인 함수부분을 디스어셈블링한 내용이다. 빨간 박스로 쳐진 두개의 함수를 따라가면서 호출되는 방법이 어떻게 되는지 확인해보겠다. 



처음으로 함수가 호출될 경우

PLT영역에서 0x80496bc 주소에 있는 값을 참조하여 점프를 하나 이 값은 PLT+6으로 되돌아오게 된다. 그 뒤에 

reloc_offset으로 0x0을 푸쉬하고 0x80482b0으로 점프한다. 



점프한 뒤에 0x80496b4(link_map 구조체 포인터라고 함)를 푸쉬하고 다시 0x80496b8에 있는 값으로 점프를 한다. 여기서 점프하는 곳이 'dl_runtime_resolve' 함수인데 해당 함수에서 실제 puts 함수의 주소를 GOT 영역에 기록한다.


이 과정이 지나고 두번째 puts 함수를 호출하는 과정을 따라가보겠다. 


위에서는 PLT+6의 위치를 가르켰던 GOT가 다른 값을 가진 것을 확인할 수 있다. 이는 실제 puts 함수의 위치를 나타내는 것을 알 수 있다. 


위 과정을 간단히 말하면, 

최초 함수를 호출할 때 PLT가 가리키는 GOT는 다시 PLT+6를 가리켜 GOT가 함수의 주소를 동적으로 할당받을 수 있도록 해주고 동일한 함수를 두 번 이상 호출하게 될 경우 이와 같은 과정이 생략되며 직접적으로 호출이 가능하다. 


해당 과정을 보다 자세하고 심도있게 파헤친 사이트가 있어 아래에 적어놓았다. 관심있으신 분들은 보길 바란다(세상엔 대단한 사람들이 너무 많아). 



사전지식 끝!! 




※ 문제풀이


이제 본격 문제풀이를 들어가도록 하겠다. 





문제는 위와 같다. 여기서 주요하게 살펴볼 점은 login 함수가 되겠다. 



다들 눈치챘겠지만 scanf 함수의 인자로 int 형 변수가 전달되었는데 & 연산자가 누락되었다. & 연산자가 누락되면 변수의 값이 전달되어 그 값을 주소 삼아 쓰기가 가능하게 된다. 


이제 GDB를 통해 함수를 봐보도록 하자. 

소스코드에서 봐도 알겠지만 welcome() 다음에  login 함수가 시작된다. 


우선 welcome 함수를 봐보도록 하겠다. 



소스코드에서 보면 알겠지만 welcome 함수에서 우리가 입력할 수 있는 글자수는 100글자로 제한되어 있다. 즉 우리는 [ebp-0x70]부터 100글자를 입력할 수 있다. 


여기서 간단히 정리하자면 welcome 함수는 단순히 내가 입력한 값을 100글자 이내로 받고 이를 출력해주는 역할을 한다. 해당 함수가 종료되면 바로 login 함수로 진입하게 된다. 



login 함수에서는 [ebp-0x10]에 위치한 값을 scanf 함수의 두번째 인자로 받는다. 이 값은 입력한 값이 저장되는 곳이다. 일단 여기까지 확인하면 문제를 풀기 위해 살펴볼 것은 다 살펴본 것 같다. 


그럼 이제 동작을 시켜볼까나!?



우선 GDB를 통해 프로그램을 동작시키고 welcome함수에서 문자열을 입력받는 곳에 A*100을 입력하고 login함수에서 scanf의 두번째 인자가 위치한 [ebp-0x10]의 값을 확인하도록 하겠다.



짜잔~


이와 같은 현상은 최초에 welcome 함수에서 scanf 함수로 사용자의 입력 값을 입력받았을 때 사용하는 스택 영역과 login 함수에서 사용하는 스택 영역이 중첩되기 때문에 발생하게 된다. 



이대로 동작시킨 다음에 숫자를 입력할 경우는 값을 입력해보면 Segmentation Fault가 나는 것을 확인할 수 있다. 

(이유를 모르시겠다면 위를 다시 확인해주세용!)


그럼 이제 모든게 끝났다. 

어떤 함수의 GOT를 덮어쓸지 결정해서 그 주소를 지정해주고 실행하고자 하는 주소로 덮어쓰면 된다. 


위 내용을 조합해서 문제를 풀면 정답을 풀 수 있다. 




문제풀이 끝!!


포너블이라는 것 자체에 대한 경험이 없다보니 이리저리 참고하면서 풀었는데도 어렵네요.

문제 자체는 간단해보였는데 베이스가 되어야하는 지식이 여럿 필요한 문제였던 거 같습니다. 


우선 조급해하지 말고 공부한다 생각하고 천천히 접근해야할 것 같습니다. 





Reference

[1] PLT와 GOT 자세히 알기 1, https://bpsecblog.wordpress.com/2016/03/07/about_got_plt_1/

[2] PLT와 GOT 자세히 알기 2(with 'yocto'), https://bpsecblog.wordpress.com/2016/03/09/about_got_plt_2/

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

[문제풀이] pwnable.kr - unlink  (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
[문제풀이] pwnable.kr - input  (0) 2017.07.09
:
Posted by einai